<!DOCTYPE html>
<html lang=en>
<head>
  <meta charset="utf-8">
  
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="format-detection" content="telephone=no,email=no,adress=no">
  <!-- Color theme for statusbar -->
  <meta name="theme-color" content="#000000" />
  <!-- 强制页面在当前窗口以独立页面显示,防止别人在框架里调用页面 -->
  <meta http-equiv="window-target" content="_top" />
  
  
  <title>大前端吊打面试官系列 | Hexo</title>
  <script src="/js/jQuery.md5.js"></script>
  <script>
    
    (function(){
      localStorage.setItem('userinfo',hex_md5('123chen'))
      
      var localData = localStorage.getItem("userinfo");
      // var localState = localStorage.getItem("state");
        if(localStorage.getItem("state") === null){
          var reason = window.prompt('请输入访问密码');
          // var promptVal = window.prompt('请输入访问密码');
          if(reason){
              //填写内容并“确定”
              var md5Prompt = hex_md5(reason)
              //点击的是“确定” 
              if (localData !== md5Prompt){
                alert('密码错误！');
                // history.back();
                location.replace(location.href); 
              }else{
                // alert('0123');
                localStorage.setItem('state',"1")
              }
          }
          else if(reason === ""){
              //未填写但“确定”
              location.replace(location.href); 
          }
          else{
            //“取消”事件
            location.replace(location.href); 
          }
        }

    })();
  </script>
 <link rel="alternate" href="/atom.xml" data="123chen" type="application/atom+xml">
  <meta name="description" content="🔥《大前端吊打面试官系列》 📚更新日志 2020&#x2F;1&#x2F;7  开始决定写近十几万字前端面试系列，规划整个系列目录提纲。 2020&#x2F;1&#x2F;8   写完部分“面试官到底考察你什么”内容。 2020&#x2F;1&#x2F;9   继续完善”面试官到底考察你什么“内容。 2020&#x2F;1&#x2F;11  开始写准备简历部分。 2020&#x2F;1&#x2F;13  完善面试前的准备内容。 2020&#x2F;1&#x2F;14  对面试准备内容做一次整体的优化。 2020">
<meta property="og:type" content="article">
<meta property="og:title" content="大前端吊打面试官系列">
<meta property="og:url" content="http://yoursite.com/2020/03/19/01/Web-interview/README/index.html">
<meta property="og:site_name" content="学习的敌人是自己的满足，要认真学习一点东西，必须从不自满开始。对自己，“学而不厌”，对人家，“诲人不倦”，我们应取这种态度。">
<meta property="og:description" content="🔥《大前端吊打面试官系列》 📚更新日志 2020&#x2F;1&#x2F;7  开始决定写近十几万字前端面试系列，规划整个系列目录提纲。 2020&#x2F;1&#x2F;8   写完部分“面试官到底考察你什么”内容。 2020&#x2F;1&#x2F;9   继续完善”面试官到底考察你什么“内容。 2020&#x2F;1&#x2F;11  开始写准备简历部分。 2020&#x2F;1&#x2F;13  完善面试前的准备内容。 2020&#x2F;1&#x2F;14  对面试准备内容做一次整体的优化。 2020">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/logo.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E7%AE%80%E5%8E%86%E6%A8%A1%E6%9D%BF.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%90%9C%E7%B4%A2vue.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%90%9C%E7%B4%A2%E9%A1%B9%E7%9B%AE.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E5%A0%86%E5%92%8C%E6%A0%88%E5%86%85%E5%AD%98.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E6%A0%88%E5%8F%98%E9%87%8F%E5%A4%8D%E5%88%B6.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E5%AF%B9%E8%B1%A1%E5%A4%8D%E5%88%B6.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E9%97%AD%E5%8C%85/%E7%A7%81%E6%9C%89%E4%BD%9C%E7%94%A8%E5%9F%9F.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E9%97%AD%E5%8C%85/%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%93%BE.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B1.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B2.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B%E5%9B%BE.png">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/instanceof.jpg">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E6%89%A7%E8%A1%8C%E6%A0%88.gif">
<meta property="og:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%B6%88%E6%81%AF%E5%BE%AA%E7%8E%AF/%E6%B6%88%E6%81%AF%E5%BE%AA%E7%8E%AF.gif">
<meta property="article:published_time" content="2020-03-19T01:12:57.000Z">
<meta property="article:modified_time" content="2020-03-27T12:41:28.918Z">
<meta property="article:author" content="溟海">
<meta property="article:tag" content="JavaScript">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://github.com/luxiangqiang/Web-interview/blob/master/images/logo.png">
  <!-- Canonical links -->
  <link rel="canonical" href="http://yoursite.com/2020/03/19/01/Web-interview/README/index.html">
  
    <link rel="alternate" href="/atom.xml" title="学习的敌人是自己的满足，要认真学习一点东西，必须从不自满开始。对自己，“学而不厌”，对人家，“诲人不倦”，我们应取这种态度。" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png" type="image/x-icon">
  
  
<link rel="stylesheet" href="/css/style.css">

  
  
  
  
<meta name="generator" content="Hexo 4.2.0"></head>


<body class="main-center" itemscope itemtype="http://schema.org/WebPage">
  <header class="header" itemscope itemtype="http://schema.org/WPHeader">
  <div class="slimContent">
    <div class="navbar-header">
      
      
      <div class="profile-block text-center">
        <a id="avatar" href="https://github.com/chen08" target="_blank">
          <img class="img-circle img-rotate" src="/images/avatar.jpg" width="200" height="200">
        </a>
        <h2 id="name" class="hidden-xs hidden-sm">溟海</h2>
        <h3 id="title" class="hidden-xs hidden-sm hidden-md">Web Developer &amp; Designer</h3>
        <small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i> Guangzhou, China</small>
      </div>
      
      <div class="search" id="search-form-wrap">

    <form class="search-form sidebar-form">
        <div class="input-group">
            <input type="text" class="search-form-input form-control" placeholder="Search" />
            <span class="input-group-btn">
                <button type="submit" class="search-form-submit btn btn-flat" onclick="return false;"><i class="icon icon-search"></i></button>
            </span>
        </div>
    </form>
    <div class="ins-search">
  <div class="ins-search-mask"></div>
  <div class="ins-search-container">
    <div class="ins-input-wrapper">
      <input type="text" class="ins-search-input" placeholder="Type something..." x-webkit-speech />
      <button type="button" class="close ins-close ins-selectable" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    </div>
    <div class="ins-section-wrapper">
      <div class="ins-section-container"></div>
    </div>
  </div>
</div>


</div>
      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
    </div>
    <nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation">
      <ul class="nav navbar-nav main-nav ">
        
        
          <!-- . -->
        
        
          <li class="menu-item menu-item-home">
            <a href="/.">
              
              <i class="icon icon-home-fill"></i>
              
              <span class="menu-title">Home</span>
            </a>
          </li>
        


        
          <!-- archives -->
        
        
          <li class="menu-item menu-item-archives">
            <a href="/archives">
              
              <i class="icon icon-archives-fill"></i>
              
              <span class="menu-title">Archives</span>
            </a>
          </li>
        


        
          <!-- categories -->
        
        
          <li class="menu-item menu-item-categories">
            <a href="/categories">
              
              <i class="icon icon-folder"></i>
              
              <span class="menu-title">Categories</span>
            </a>
          </li>
        


        
          <!-- tags -->
        
        
          <li class="menu-item menu-item-tags">
            <a href="/tags">
              
              <i class="icon icon-tags"></i>
              
              <span class="menu-title">Tags</span>
            </a>
          </li>
        


        
          <!-- repository -->
        
        
          <li class="menu-item menu-item-repository">
            <a href="/repository">
              
              <i class="icon icon-project"></i>
              
              <span class="menu-title">Repository</span>
            </a>
          </li>
        


        
          <!-- books -->
        
        
          <li class="menu-item menu-item-books">
            <a href="/books">
              
              <i class="icon icon-book-fill"></i>
              
              <span class="menu-title">Books</span>
            </a>
          </li>
        


        
          <!-- links -->
        
        
          <li class="menu-item menu-item-links">
            <a href="/links">
              
              <i class="icon icon-friendship"></i>
              
              <span class="menu-title">Links</span>
            </a>
          </li>
        


        
          <!-- about -->
        
        
          <li class="menu-item menu-item-about">
            <a href="/about">
              
              <i class="icon icon-cup-fill"></i>
              
              <span class="menu-title">About</span>
            </a>
          </li>
        


        
          <!-- navigation/webstack/index.html -->
        
        
          <li class="menu-item menu-item-navigation">
            <a href="/navigation/webstack/index.html">
              
              <i class="icon icon-delicious"></i>
              
              <span class="menu-title">Navigation</span>
            </a>
          </li>
        


        
          <!-- navigation/webstack/word.html -->
        
        
          <li style="display: none;" class="menu-item menu-item-fixed">
            <a href="/navigation/webstack/word.html">
              
              <i class="icon icon-delicious"></i>
              
              <span class="menu-title">menu.fixed</span>
            </a>
          </li>
        


        
      </ul>

      
	
    <ul class="social-links">
    	
        <li><a href="https://github.com/cofess" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="http://weibo.com/cofess" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="https://twitter.com/iwebued" target="_blank" title="Twitter" data-toggle=tooltip data-placement=top><i class="icon icon-twitter"></i></a></li>
        
        <li><a href="https://www.behance.net/cofess" target="_blank" title="Behance" data-toggle=tooltip data-placement=top><i class="icon icon-behance"></i></a></li>
        
        <li><a href="/atom.xml" target="_blank" title="Rss" data-toggle=tooltip data-placement=top><i class="icon icon-rss"></i></a></li>
        
    </ul>

    </nav>
  </div>
</header>

  
    <aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    
      <div class="widget">
    <h3 class="widget-title">Board</h3>
    <div class="widget-body">
        <div id="board">
            <div class="content">
                <p>欢迎交流与分享经验!</p>
            </div>
        </div>
    </div>
</div>

    
      
  <div class="widget">
    <h3 class="widget-title">Categories</h3>
    <div class="widget-body">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/1-WEB%E5%89%8D%E7%AB%AF/">1.WEB前端</a><span class="category-list-count">15</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/2-%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/">2.编程语言</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/3-%E4%BA%A7%E5%93%81%E8%AE%BE%E8%AE%A1/">3.产品设计</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/4-%E7%AE%A1%E7%90%86%E8%90%A5%E9%94%80/">4.管理营销</a><span class="category-list-count">6</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/5-%E6%8A%80%E8%83%BD%E6%8F%90%E5%8D%87/">5.技能提升</a><span class="category-list-count">16</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/6-%E8%AF%BB%E4%B9%A6%E6%80%BB%E7%BB%93/">6.读书总结</a><span class="category-list-count">8</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">Tags</h3>
    <div class="widget-body">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/JavaScript/" rel="tag">JavaScript</a><span class="tag-list-count">15</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/JavaScript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" rel="tag">JavaScript设计模式</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Office/" rel="tag">Office</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/PHP/" rel="tag">PHP</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%86%99%E4%BD%9C/" rel="tag">写作</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%9F%BA%E9%87%91/" rel="tag">基金</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%AD%A6%E4%B9%A0/" rel="tag">学习</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%B7%A5%E4%BD%9C/" rel="tag">工作</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%80%9D%E8%80%83/" rel="tag">思考</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E6%B8%85%E5%8D%95/" rel="tag">清单</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E7%9B%AE%E6%A0%87/" rel="tag">目标</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E7%BB%83%E4%B9%A0/" rel="tag">练习</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%8B%B1%E8%AF%AD/" rel="tag">英语</a><span class="tag-list-count">6</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%AE%A1%E5%88%92/" rel="tag">计划</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%AF%AD%E6%B3%95/" rel="tag">语法</a><span class="tag-list-count">4</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E9%9A%8F%E7%AC%94/" rel="tag">随笔</a><span class="tag-list-count">8</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E9%9D%A2%E8%AF%95/" rel="tag">面试</a><span class="tag-list-count">1</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget-body tagcloud">
      <a href="/tags/JavaScript/" style="font-size: 14px;">JavaScript</a> <a href="/tags/JavaScript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" style="font-size: 13px;">JavaScript设计模式</a> <a href="/tags/Office/" style="font-size: 13.33px;">Office</a> <a href="/tags/PHP/" style="font-size: 13.33px;">PHP</a> <a href="/tags/%E5%86%99%E4%BD%9C/" style="font-size: 13.17px;">写作</a> <a href="/tags/%E5%9F%BA%E9%87%91/" style="font-size: 13.17px;">基金</a> <a href="/tags/%E5%AD%A6%E4%B9%A0/" style="font-size: 13px;">学习</a> <a href="/tags/%E5%B7%A5%E4%BD%9C/" style="font-size: 13px;">工作</a> <a href="/tags/%E6%80%9D%E8%80%83/" style="font-size: 13px;">思考</a> <a href="/tags/%E6%B8%85%E5%8D%95/" style="font-size: 13px;">清单</a> <a href="/tags/%E7%9B%AE%E6%A0%87/" style="font-size: 13px;">目标</a> <a href="/tags/%E7%BB%83%E4%B9%A0/" style="font-size: 13px;">练习</a> <a href="/tags/%E8%8B%B1%E8%AF%AD/" style="font-size: 13.67px;">英语</a> <a href="/tags/%E8%AE%A1%E5%88%92/" style="font-size: 13.17px;">计划</a> <a href="/tags/%E8%AF%AD%E6%B3%95/" style="font-size: 13.5px;">语法</a> <a href="/tags/%E9%9A%8F%E7%AC%94/" style="font-size: 13.83px;">随笔</a> <a href="/tags/%E9%9D%A2%E8%AF%95/" style="font-size: 13px;">面试</a>
    </div>
  </div>

    
      
  <div class="widget">
    <h3 class="widget-title">Archive</h3>
    <div class="widget-body">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/20120/04/">April 20120</a><span class="archive-list-count">6</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/20120/03/">March 20120</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/05/">May 2020</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/04/">April 2020</a><span class="archive-list-count">12</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/03/">March 2020</a><span class="archive-list-count">14</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/11/">November 2019</a><span class="archive-list-count">10</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget-body">
      <ul class="recent-post-list list-unstyled no-thumbnail">
        
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/5-%E6%8A%80%E8%83%BD%E6%8F%90%E5%8D%87/">5.技能提升</a>
              </p>
              <p class="item-title">
                <a href="/20120/04/21/05/fund/%E5%9F%BA%E9%87%91%E5%9F%BA%E7%A1%80/" class="title">基金基础</a>
              </p>
              <p class="item-date">
                <time datetime="+020120-04-21T01:12:57.000Z" itemprop="datePublished">20120-04-21</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/5-%E6%8A%80%E8%83%BD%E6%8F%90%E5%8D%87/">5.技能提升</a>
              </p>
              <p class="item-title">
                <a href="/20120/04/21/05/study/%E5%AD%A6%E4%B9%A0/" class="title">学习</a>
              </p>
              <p class="item-date">
                <time datetime="+020120-04-21T01:12:57.000Z" itemprop="datePublished">20120-04-21</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/5-%E6%8A%80%E8%83%BD%E6%8F%90%E5%8D%87/">5.技能提升</a>
              </p>
              <p class="item-title">
                <a href="/20120/04/13/05/%E4%BB%8A%E6%97%A5%E8%AE%A1%E5%88%92/" class="title">今日计划</a>
              </p>
              <p class="item-date">
                <time datetime="+020120-04-13T01:12:57.000Z" itemprop="datePublished">20120-04-13</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/5-%E6%8A%80%E8%83%BD%E6%8F%90%E5%8D%87/">5.技能提升</a>
              </p>
              <p class="item-title">
                <a href="/20120/04/03/05/office/Excel%E5%AD%A6%E4%B9%A0/" class="title">Excel学习</a>
              </p>
              <p class="item-date">
                <time datetime="+020120-04-03T01:12:57.000Z" itemprop="datePublished">20120-04-03</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/5-%E6%8A%80%E8%83%BD%E6%8F%90%E5%8D%87/">5.技能提升</a>
              </p>
              <p class="item-title">
                <a href="/20120/04/03/05/office/PPT%E5%AD%A6%E4%B9%A0/" class="title">PPT学习</a>
              </p>
              <p class="item-date">
                <time datetime="+020120-04-03T01:12:57.000Z" itemprop="datePublished">20120-04-03</time>
              </p>
            </div>
          </li>
          
      </ul>
    </div>
  </div>
  

    
  </div>
</aside>

  
  
<aside class="sidebar sidebar-toc collapse" id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar">
  <span class="toggle-btn-absolute">
    <a class="toggle-btn" data-toggle="collapse" href="#collapseToc" aria-expanded="true" title="Catalogue" role="button">
      <i class="text-in icon icon-close"></i>
    </a>
  </span>
  <div class="slimContent">
    <nav id="toc" class="article-toc">
      <h3 class="toc-title">Catalogue</h3>
      <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#🔥《大前端吊打面试官系列》"><span class="toc-number">1.</span> <span class="toc-text">🔥《大前端吊打面试官系列》</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#📚更新日志"><span class="toc-number">1.1.</span> <span class="toc-text">📚更新日志</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#📖目录"><span class="toc-number">1.2.</span> <span class="toc-text">📖目录</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#本系列介绍"><span class="toc-number">1.3.</span> <span class="toc-text">本系列介绍</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#❓俺为什么要写这一系列？"><span class="toc-number">1.3.1.</span> <span class="toc-text">❓俺为什么要写这一系列？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#⛏️-本系列有什么特点？"><span class="toc-number">1.3.2.</span> <span class="toc-text">⛏️ 本系列有什么特点？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#🏆本系列的目标"><span class="toc-number">1.3.3.</span> <span class="toc-text">🏆本系列的目标</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#👨‍💻不适合人群"><span class="toc-number">1.4.</span> <span class="toc-text">👨‍💻不适合人群</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#⚠️阅读须知"><span class="toc-number">1.5.</span> <span class="toc-text">⚠️阅读须知</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#💬面试到底考察你什么？"><span class="toc-number">1.6.</span> <span class="toc-text">💬面试到底考察你什么？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1、基础是否扎实过硬"><span class="toc-number">1.6.0.1.</span> <span class="toc-text">1、基础是否扎实过硬</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2、思路是否清晰明确"><span class="toc-number">1.6.0.2.</span> <span class="toc-text">2、思路是否清晰明确</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3、能否写高质量代码的能力"><span class="toc-number">1.6.0.3.</span> <span class="toc-text">3、能否写高质量代码的能力</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4、是否有优化性能的能力"><span class="toc-number">1.6.0.4.</span> <span class="toc-text">4、是否有优化性能的能力</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5、是否有快速学习能力"><span class="toc-number">1.6.0.5.</span> <span class="toc-text">5、是否有快速学习能力</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6、是否有人际沟通能力"><span class="toc-number">1.6.0.6.</span> <span class="toc-text">6、是否有人际沟通能力</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7、是否具备强大的综合能力"><span class="toc-number">1.6.0.7.</span> <span class="toc-text">7、是否具备强大的综合能力</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#✏️面试前如何做准备？"><span class="toc-number">1.7.</span> <span class="toc-text">✏️面试前如何做准备？</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#一、简历准备"><span class="toc-number">1.7.1.</span> <span class="toc-text">一、简历准备</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#简历形式"><span class="toc-number">1.7.1.1.</span> <span class="toc-text">简历形式</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#非统一简历"><span class="toc-number">1.7.1.1.1.</span> <span class="toc-text">非统一简历</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#简约大气"><span class="toc-number">1.7.1.1.2.</span> <span class="toc-text">简约大气</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#真实简历"><span class="toc-number">1.7.1.1.3.</span> <span class="toc-text">真实简历</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#PDF-版本"><span class="toc-number">1.7.1.1.4.</span> <span class="toc-text">PDF 版本</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#简历详情"><span class="toc-number">1.7.1.2.</span> <span class="toc-text">简历详情</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#简历页数"><span class="toc-number">1.7.1.2.1.</span> <span class="toc-text">简历页数</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#个人闪光点"><span class="toc-number">1.7.1.2.2.</span> <span class="toc-text">个人闪光点</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#谨慎熟悉、精通关键字"><span class="toc-number">1.7.1.2.3.</span> <span class="toc-text">谨慎熟悉、精通关键字</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#项目经历"><span class="toc-number">1.7.1.2.4.</span> <span class="toc-text">项目经历</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#如何找项目？"><span class="toc-number">1.7.1.2.5.</span> <span class="toc-text">如何找项目？</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#项目描述"><span class="toc-number">1.7.1.2.6.</span> <span class="toc-text">项目描述</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#项目闪光点"><span class="toc-number">1.7.1.2.7.</span> <span class="toc-text">项目闪光点</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#小技巧"><span class="toc-number">1.7.1.3.</span> <span class="toc-text">小技巧</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#大忌"><span class="toc-number">1.7.1.4.</span> <span class="toc-text">大忌</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#二、了解公司"><span class="toc-number">1.7.2.</span> <span class="toc-text">二、了解公司</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1、面试内容"><span class="toc-number">1.7.2.1.</span> <span class="toc-text">1、面试内容</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2、主要业务产品"><span class="toc-number">1.7.2.2.</span> <span class="toc-text">2、主要业务产品</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3、发展前景"><span class="toc-number">1.7.2.3.</span> <span class="toc-text">3、发展前景</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#JavaScript-基础知识点"><span class="toc-number">1.8.</span> <span class="toc-text">JavaScript 基础知识点</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#数据类型"><span class="toc-number">1.8.1.</span> <span class="toc-text">数据类型</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1、数据类型的存储形式"><span class="toc-number">1.8.1.1.</span> <span class="toc-text">1、数据类型的存储形式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2、Null"><span class="toc-number">1.8.1.2.</span> <span class="toc-text">2、Null</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3、数据类型的判断"><span class="toc-number">1.8.1.3.</span> <span class="toc-text">3、数据类型的判断</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4、类型转换"><span class="toc-number">1.8.1.4.</span> <span class="toc-text">4、类型转换</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#显式类型转换"><span class="toc-number">1.8.1.4.1.</span> <span class="toc-text">显式类型转换</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#5、四则运算"><span class="toc-number">1.8.1.5.</span> <span class="toc-text">5、四则运算</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#加法运算"><span class="toc-number">1.8.1.5.1.</span> <span class="toc-text">加法运算</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#其他运算"><span class="toc-number">1.8.1.5.2.</span> <span class="toc-text">其他运算</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#6、逻辑运算符"><span class="toc-number">1.8.1.6.</span> <span class="toc-text">6、逻辑运算符</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#7、比较运算符"><span class="toc-number">1.8.1.7.</span> <span class="toc-text">7、比较运算符</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#this"><span class="toc-number">1.8.2.</span> <span class="toc-text">this</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#new"><span class="toc-number">1.8.3.</span> <span class="toc-text">new</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#闭包"><span class="toc-number">1.8.4.</span> <span class="toc-text">闭包</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#原型和原型链"><span class="toc-number">1.8.5.</span> <span class="toc-text">原型和原型链</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#继承"><span class="toc-number">1.8.6.</span> <span class="toc-text">继承</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#经典继承（构造函数）"><span class="toc-number">1.8.6.1.</span> <span class="toc-text">经典继承（构造函数）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#组合继承"><span class="toc-number">1.8.6.2.</span> <span class="toc-text">组合继承</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#原型继承"><span class="toc-number">1.8.6.3.</span> <span class="toc-text">原型继承</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#寄生式继承"><span class="toc-number">1.8.6.4.</span> <span class="toc-text">寄生式继承</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#垃圾回收机制"><span class="toc-number">1.8.7.</span> <span class="toc-text">垃圾回收机制</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#两种垃圾回收策略"><span class="toc-number">1.8.7.1.</span> <span class="toc-text">两种垃圾回收策略</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#标记清除法"><span class="toc-number">1.8.7.2.</span> <span class="toc-text">标记清除法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#引用计数法"><span class="toc-number">1.8.7.3.</span> <span class="toc-text">引用计数法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#如何管理内存"><span class="toc-number">1.8.7.4.</span> <span class="toc-text">如何管理内存</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#深拷贝和浅拷贝"><span class="toc-number">1.8.8.</span> <span class="toc-text">深拷贝和浅拷贝</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#异步编程"><span class="toc-number">1.8.9.</span> <span class="toc-text">异步编程</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#执行上下文"><span class="toc-number">1.8.9.1.</span> <span class="toc-text">执行上下文</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#执行栈"><span class="toc-number">1.8.9.2.</span> <span class="toc-text">执行栈</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#宏任务"><span class="toc-number">1.8.9.3.</span> <span class="toc-text">宏任务</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#微任务"><span class="toc-number">1.8.9.4.</span> <span class="toc-text">微任务</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#ES6-基础知识点"><span class="toc-number">1.9.</span> <span class="toc-text">ES6 基础知识点</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#变量提升"><span class="toc-number">1.9.1.</span> <span class="toc-text">变量提升</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#var、let、const"><span class="toc-number">1.9.2.</span> <span class="toc-text">var、let、const</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#map、filter、reduce"><span class="toc-number">1.9.3.</span> <span class="toc-text">map、filter、reduce</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#map"><span class="toc-number">1.9.3.1.</span> <span class="toc-text">map</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#filter"><span class="toc-number">1.9.3.2.</span> <span class="toc-text">filter</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#reduce"><span class="toc-number">1.9.3.3.</span> <span class="toc-text">reduce</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Proxy"><span class="toc-number">1.9.4.</span> <span class="toc-text">Proxy</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#字面量定义"><span class="toc-number">1.9.4.1.</span> <span class="toc-text">字面量定义</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES6-中的-Class-定义"><span class="toc-number">1.9.4.2.</span> <span class="toc-text">ES6 中的 Class 定义</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Object-definedProperty"><span class="toc-number">1.9.4.3.</span> <span class="toc-text">Object.definedProperty()</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Proxy-代理"><span class="toc-number">1.9.4.4.</span> <span class="toc-text">Proxy 代理</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ES6-7-的异步编程"><span class="toc-number">1.9.5.</span> <span class="toc-text">ES6&#x2F;7 的异步编程</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Generator-生成器"><span class="toc-number">1.9.5.1.</span> <span class="toc-text">Generator 生成器</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Promise"><span class="toc-number">1.9.5.2.</span> <span class="toc-text">Promise</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#async-及-await"><span class="toc-number">1.9.5.3.</span> <span class="toc-text">async 及 await</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#模块化"><span class="toc-number">1.9.6.</span> <span class="toc-text">模块化</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#方式一：函数"><span class="toc-number">1.9.6.1.</span> <span class="toc-text">方式一：函数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#方式二：立即执行函数"><span class="toc-number">1.9.6.2.</span> <span class="toc-text">方式二：立即执行函数</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#方式三：CommonJS"><span class="toc-number">1.9.6.3.</span> <span class="toc-text">方式三：CommonJS</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#方式四：AMD-和-CMD"><span class="toc-number">1.9.6.4.</span> <span class="toc-text">方式四：AMD 和 CMD</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#方式五：ES6-Moudle"><span class="toc-number">1.9.6.5.</span> <span class="toc-text">方式五：ES6 Moudle</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#小结"><span class="toc-number">1.9.6.6.</span> <span class="toc-text">小结</span></a></li></ol></li></ol></li></ol></li></ol>
    </nav>
  </div>
</aside>

<main class="main" role="main">
  <!-- 引入百度的思维导图库 -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/kity@2.0.4/dist/kity.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script>
<script defer="true" type="text/javascript" src="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.2.0/dist/mindmap.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.2.0/dist/mindmap.min.css">
<!-- 引入百度的思维导图库 -->
<div class="content">
  <article id="post-01/Web-interview/README" class="article article-type-post" itemscope itemtype="http://schema.org/BlogPosting">
    
    <div class="article-header">
      
        
  
    <h1 class="article-title" itemprop="name">
      大前端吊打面试官系列
    </h1>
  

      
      <div class="article-meta">
        <span class="article-date">
    <i class="icon icon-calendar-check"></i>
	<a href="/2020/03/19/01/Web-interview/README/" class="article-date">
	  <time datetime="2020-03-19T01:12:57.000Z" itemprop="datePublished">2020-03-19</time>
	</a>
</span>
        
  <span class="article-category">
    <i class="icon icon-folder"></i>
    <a class="article-category-link" href="/categories/1-WEB%E5%89%8D%E7%AB%AF/">1.WEB前端</a>
  </span>

        
  <span class="article-tag">
    <i class="icon icon-tags"></i>
	<a class="article-tag-link" href="/tags/JavaScript/" rel="tag">JavaScript</a>
  </span>


        

	<span class="article-read hidden-xs">
    	<i class="icon icon-eye-fill" aria-hidden="true"></i>
    	<span id="/2020/03/19/01/Web-interview/README/" class="leancloud_visitors"  data-flag-title="大前端吊打面试官系列">0</span>
    </span>

        <span class="post-comment"><i class="icon icon-comment"></i> <a href="/2020/03/19/01/Web-interview/README/#comments" class="article-comment-link">Comments</a></span>
        
	
		<span class="post-wordcount hidden-xs" itemprop="wordCount">Word Count: 26.5k(words)</span>
	
	
		<span class="post-readcount hidden-xs" itemprop="timeRequired">Read Count: 97(minutes)</span>
	

      </div>
    </div>
    <div class="article-entry marked-body" itemprop="articleBody">
      
        <h1 id="🔥《大前端吊打面试官系列》"><a href="#🔥《大前端吊打面试官系列》" class="headerlink" title="🔥《大前端吊打面试官系列》"></a>🔥《大前端吊打面试官系列》</h1><p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/logo.png" alt=""></p>
<h2 id="📚更新日志"><a href="#📚更新日志" class="headerlink" title="📚更新日志"></a>📚更新日志</h2><ul>
<li><strong>2020/1/7</strong>  开始决定写近十几万字前端面试系列，规划整个系列目录提纲。</li>
<li><strong>2020/1/8</strong>   写完部分“面试官到底考察你什么”内容。</li>
<li><strong>2020/1/9</strong>   继续完善”面试官到底考察你什么“内容。</li>
<li><strong>2020/1/11</strong>  开始写准备简历部分。</li>
<li><strong>2020/1/13</strong>  完善面试前的准备内容。</li>
<li><strong>2020/1/14</strong>  对面试准备内容做一次整体的优化。</li>
<li><strong>2020/1/15</strong>  开始写 JavaScript 基础知识部分 。</li>
<li><strong>2020/1/16</strong>  写数据类型中的七大模块部分 。</li>
<li><strong>2020/1/17</strong>  写 this、闭包等重点部分。</li>
<li><strong>2020/1/30</strong>   写消息循环机制的原理</li>
<li><strong>2020/02/02</strong>  补充 new 的实现原理</li>
<li><strong>2020/02/03</strong>  补充继承等知识内容，以及一些参考文献</li>
<li><strong>2020/02/04</strong>  补充垃圾回收机制等知识内容</li>
<li><strong>2020/02/05</strong>  补充深浅拷贝等知识内容</li>
<li><strong>会持续更新中…</strong></li>
</ul>
<hr>
<h2 id="📖目录"><a href="#📖目录" class="headerlink" title="📖目录"></a>📖目录</h2><ul>
<li><p><a href="#本系列介绍">本系列介绍</a></p>
<ul>
<li><a href="#❓俺为什么要写这一系列？">❓俺为什么要写本系列？</a></li>
<li><a href="#⛏️本系列有什么特点？">⛏️本系列有什么特点？</a></li>
<li><a href="#🏆本系列的目标">🏆本系列的目标</a></li>
<li><a href="#👨‍💻不适合人群">👨‍💻不适合人群</a></li>
<li><a href="#⚠️阅读须知">⚠️阅读须知</a></li>
</ul>
</li>
<li><p><a href="#💬面试到底考察你什么？">💬面试到底考察你什么？</a></p>
<ul>
<li><a href="#1、基础是否扎实过硬">基础是否扎实过硬</a></li>
<li><a href="#2、思路是否清晰明确">思路是否清晰明确</a></li>
<li><a href="#3、能否写高质量代码的能力">能否写高质量代码的能力</a></li>
<li><a href="#4、是否有优化性能的能力">是否有优化性能的能力</a></li>
<li><a href="#5、是否有快速学习能力">是否有快速学习能力</a></li>
<li><a href="#6、是否有人际沟通能力">是否有人际沟通能力</a></li>
<li><a href="#7、是否具备强大的综合能力">是否具备强大的综合能力</a></li>
</ul>
</li>
<li><p><a href="#✏️面试前如何做准备？">✏️面试前如何做准备？</a></p>
<ul>
<li><a href="#一、简历准备">简历准备</a><ul>
<li><a href="#简历形式">简历形式 </a><ul>
<li><a href="#非统一简历">非统一简历</a></li>
<li><a href="#简约大气">简约大气</a></li>
<li><a href="#真实简历">真实简历</a></li>
<li><a href="#PDF版本">PDF版本</a></li>
</ul>
</li>
<li><a href="#简历详情">简历详情</a><ul>
<li><a href="#简历页数">简历页数</a></li>
<li><a href="#个人闪光点">个人闪光点</a></li>
<li><a href="#谨慎熟悉、精通关键字">谨慎熟悉、精通关键字</a></li>
<li><a href="#项目经历">项目经历</a></li>
</ul>
</li>
<li><a href="#小技巧">小技巧</a></li>
<li><a href="#大忌">大忌</a></li>
</ul>
</li>
<li><a href="#了解公司">了解公司</a></li>
<li><a href="#1、面试内容">面试内容</a></li>
<li><a href="#2、主要业务产品">主要业务产品</a></li>
<li><a href="#3、发展前景">发展前景</a></li>
</ul>
</li>
<li><p><a href="#JavaScript基础知识点">JavaScript 基础知识点</a></p>
<ul>
<li><p><a href="#数据类型">数据类型</a></p>
<ul>
<li><a href="#1、数据类型的存储形式">1、数据类型的存储形式</a> </li>
<li><a href="#2、Null">2、Null</a> </li>
<li><a href="#3、数据类型的判断">3、数据类型的判断</a> </li>
<li><a href="#4、类型转换">4、类型转换</a> </li>
<li><a href="#5、四则运算">5、四则运算</a> </li>
<li><a href="#6、逻辑运算符">6、逻辑运算符</a> </li>
<li><a href="#7、比较运算符">7、比较运算符</a> </li>
</ul>
</li>
<li><p><a href="#this">this</a></p>
</li>
<li><p><a href="#new">new</a></p>
</li>
<li><p><a href="#闭包">闭包</a></p>
</li>
<li><p><a href="#原型和原型链">原型和原型链</a></p>
</li>
<li><p><a href="#继承">继承</a></p>
<ul>
<li><a href="#经典继承">经典继承</a>  </li>
<li><a href="#组合继承">组合继承</a>  </li>
<li><a href="#原型继承">原型继承</a>  </li>
<li><a href="#寄生式继承">寄生式继承</a>  </li>
</ul>
</li>
<li><p><a href="#垃圾回收机制">垃圾回收机制</a></p>
<ul>
<li><a href="#两种垃圾回收策略">两种垃圾回收策略</a> </li>
<li><a href="#标记清除法">标记清除法</a> </li>
<li><a href="#引用计数法">引用计数法</a> </li>
<li><a href="#如何管理内存">如何管理内存</a> </li>
</ul>
</li>
<li><p><a href="#深拷贝和浅拷贝">深拷贝和浅拷贝</a></p>
</li>
<li><p><a href="#异步编程">异步编程</a></p>
<ul>
<li><a href="#执行上下文">执行上下文</a> </li>
<li><a href="#执行栈">执行栈</a> </li>
<li><a href="#宏任务">宏任务</a> </li>
<li><a href="#微任务">微任务</a> </li>
<li><a href="#运行机制">运行机制</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><a href="#ES6基础知识点">ES6 基础知识点</a><ul>
<li><a href="#变量提升">变量提升</a> </li>
<li><a href="#var、let、const">var、let、const</a> </li>
<li><a href="#map、filter、reduce">map、filter、reduce </a><ul>
<li><a href="#map">map</a> </li>
<li><a href="#filter">filter</a> </li>
<li><a href="#reduce">reduce</a> </li>
</ul>
</li>
<li><a href="#Proxy">Proxy</a> <ul>
<li><a href="#字面量定义">字面量定义</a></li>
<li><a href="#ES6中的Class定义">ES6 中的 Class 定义</a></li>
<li><a href="#Object.definedProperty()">Object.definedProperty()</a></li>
<li><a href="#Proxy代理">Proxy 代理</a></li>
</ul>
</li>
<li><a href="#ES6/7的异步编程">ES6/7 的异步编程</a> <ul>
<li><a href="#Generator生成器">Generator 生成器</a></li>
<li><a href="#Promise">Promise</a></li>
<li><a href="#async及await">async 及 await</a></li>
</ul>
</li>
<li><a href="#模块化">模块化</a><ul>
<li><a href="#方式一：函数">方式一：函数</a></li>
<li><a href="#方式二：立即执行函数">方式二：立即执行函数</a></li>
<li><a href="#方式三：CommonJS">方式三：CommonJS</a></li>
<li><a href="#方式四：AMD和CMD">方式四：AMD 和 CMD</a></li>
<li><a href="#方式五：ES6Moudle">方式五：ES6 Moudle</a></li>
<li><a href="#小结">小结</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="本系列介绍"><a href="#本系列介绍" class="headerlink" title="本系列介绍"></a>本系列介绍</h2><p>嗨！各位好，额是小鹿，一位被耽误的前端打杂师。</p>
<p>本系列将会把大前端所有常考面试知识点以及如何准备面试进行全面复盘。按照常理，是做不到完全全面的复盘的。但是希望俺的这一系列能够帮助你在接下来的春招中能够收获自己满意的 offer。有一点说明一下，之所以下决心开始写本系列内容，因为俺觉得这也是一次给俺自己查缺补漏的过程，同时又能分享给学习前端的其他开发者，无论是你前端工作多年的开发者还是一个在校的初学者，欢迎为本系列提出合理的建议，俺会在后期不断完善本系列内容。</p>
<h3 id="❓俺为什么要写这一系列？"><a href="#❓俺为什么要写这一系列？" class="headerlink" title="❓俺为什么要写这一系列？"></a>❓俺为什么要写这一系列？</h3><p>俺个人是野鸡大学出身，无学历，无大厂背景，但是在自学中经历了各种苦逼的事情，正是因为这种苦逼的经历，让俺收获了很多，同时俺在大二的时候开始写作在公众号分享自学的经历和技术。在写作分享的过程中遇到了很多非科班以及自学者的交流，从和读者交流中得出，存在自学者知识的零散性和非科班面对毕业找工作的困惑等，所以让俺在 2020 年有了这一新的打算。</p>
<blockquote>
<p>PS：其实俺个人学前端没有多久，第一份工作是自学四个月之后，独自跑去一线城市面试，拿到了自我感觉满意的几个 offer（非大厂）。由于环境因素，所有 offer 全部放弃，也成功错过大三的春招和秋招，后来我陷入了对人生的思考……。</p>
</blockquote>
<p>直到今年 2020 年，俺决定开始从零全面整理前端面试相关知识点。虽然系列的名字听起来挺牛 B 的，但是可能写的达不到很多人的期望，所以对本系列期望不要太过高。俺也会按照掘金小册的规模和要求去写。最后，俺给本系列设定了一下几个写作目标和特点。</p>
<h3 id="⛏️-本系列有什么特点？"><a href="#⛏️-本系列有什么特点？" class="headerlink" title="⛏️ 本系列有什么特点？"></a>⛏️ 本系列有什么特点？</h3><ul>
<li><strong>文章中会加一些通俗易懂的动画。</strong></li>
<li><strong>能够经历时间的考验。</strong></li>
<li><strong>实时更新、常年更新。</strong></li>
<li><strong>全面性（广度和深度）。</strong></li>
<li><strong>和读者一块完成。</strong></li>
</ul>
<p>一篇好的文章不是别人说他有多好就有多好，而是他能够经受住时间的考验，能够持续的给读者带来新的认识和帮助，同时为了考虑到很多初学者，俺这个业余的动画师会在文章中增加一些<strong>动画演示</strong>。</p>
<p>俺自己也买过很多的付费资料，也包括大佬们写的小册子，写的很不错、很受益。俺的这一系列虽不能和大佬们的小册相比，但是尽俺最大努力去写。可能有些知识点暂时不能做到很详细，但是在后期会对文章无论广度还是深度上不断的再进行打磨。</p>
<p>看到过很多文章下读者的评论，考虑到很多读者说到广度和深度上的问题，尽管是付费的内容，也有写的不尽人意的地方，这也是作者不可避免的。本系列也不可能一次将知识点写到位，俺想而是通过后期于不断与读者的交流中打磨。考虑到俺也是一个上班族，所以俺只能利用所有的下班时间和周末时间去完善本系列当的内容。</p>
<p>还有一点就是，这个系列并不是俺个人完成的，而是和所有阅读这一系列文章的读者一块完成的。因为一个人的能力有限，所有希望阅读本系列的读者可以补充文章的不足点，或者你在面试中遇到的一些问题，俺会通过筛选、搜集资料将内容进行实时补充，同时俺也在 Github 创建了一个仓库，专门来同步本系列的文章，如果本系列写得受欢迎，后期俺还会开展其他系列。（<a href="https://github.com/luxiangqiang/Web-interview" target="_blank" rel="noopener">Github 仓库可以戳这里咯~</a>）</p>
<h3 id="🏆本系列的目标"><a href="#🏆本系列的目标" class="headerlink" title="🏆本系列的目标"></a>🏆本系列的目标</h3><ul>
<li>希望帮助你找到一份满意的工作。</li>
<li>完善前端知识体系。</li>
<li>增强前端的“基本功”。</li>
</ul>
<h2 id="👨‍💻不适合人群"><a href="#👨‍💻不适合人群" class="headerlink" title="👨‍💻不适合人群"></a>👨‍💻不适合人群</h2><ul>
<li>想通过本篇一步登天、走捷径的不建议阅读滴~。</li>
<li>仅仅想通过这一系列文章就进入 BAT 的，也不建议阅读滴~。</li>
<li>认为文章没价值的，没营养，给他人传播负能量，在评论区抱怨的也不建议阅读滴~。</li>
</ul>
<h2 id="⚠️阅读须知"><a href="#⚠️阅读须知" class="headerlink" title="⚠️阅读须知"></a>⚠️阅读须知</h2><ul>
<li>本系列完全开源免费。（如想付费，现金可以吗？）</li>
<li>本系列会在知识点的广度和深度上实时更新，常年更新。<strong>地球不爆炸，小鹿不放假</strong>。</li>
<li>本系列会与公众号「<strong>小鹿动画学编程</strong>」以及 <a href="https://github.com/luxiangqiang/Web-interview" target="_blank" rel="noopener">Github</a> 同步更新，转载请说明出处，谢谢您的转载分享。</li>
</ul>
<h2 id="💬面试到底考察你什么？"><a href="#💬面试到底考察你什么？" class="headerlink" title="💬面试到底考察你什么？"></a>💬面试到底考察你什么？</h2><p>无论是前端的面试还是其他职位的面试，一个重点的问题就是公司以什么标准来考察你？面试官到底考察你什么能力？之前很多朋友跟俺说，只要你技术好，能干活，基础扎实，有沟通能力等，面试基本基本没什么问题。那么问题来了，技术有多好叫做技术好？干活效率有多高叫做能干活？沟通能力有多强才算标准以及除了这些能力之外，面试还主要考察应聘者的哪些能力呢？有没有一个衡量的标准呢？</p>
<p>那么根据俺看的一些面试书籍、付费资料、论坛以及与面试的读者朋友交流中，再加上俺之前的一些不同公司的面试经历俺想谈谈个人的一些经验？（纯属个人经验，不喜勿喷哦！）</p>
<p>公司设定了一定的笔试也好，电话面视频面也好，还是面议也好，其实综合来看，公司选人标准就是从以下 7 个能力方面出发的。（PS：对于实习生和应届毕业生来说，相信这六个能力已经全部概括了所有的面试内容，特殊公司要求除外哦~）</p>
<ul>
<li><strong>基础是否扎实过硬;</strong></li>
<li><strong>思路是否清晰明确;</strong></li>
<li><strong>能否写高质量代码的能力;</strong></li>
<li><strong>能否有优化性能的能力;</strong></li>
<li><strong>能否有快速学习能力;</strong></li>
<li><strong>能否有人际沟通能力;</strong></li>
<li><strong>是否具备强大的综合能力</strong>。</li>
</ul>
<p>这些能力相信大家可以看出，不是在短时间内一蹴而就的，而是经过长时间的积累和练习，看过《<strong>刻意练习</strong>》这本书的小伙伴们知道，不仅注重日常学习中的练习，更要给自己设定一个高目标以及在练习中不断的进行反馈、反思、总结，才能有可能达到以上几个综合的能力。那下面，俺根据个人的自学经验分别对以上几个能力展开唠唠。</p>
<h4 id="1、基础是否扎实过硬"><a href="#1、基础是否扎实过硬" class="headerlink" title="1、基础是否扎实过硬"></a>1、基础是否扎实过硬</h4><p>基础的重要性俺也不想过多的强调，大多数的的应聘者都基本知道面试最主要的考试应聘者的基础是否扎实能力。一面，二面以及一些笔试面都是考察你的基本功。相信很多初学者对掌握一个扎实的基础没有概念，所以俺在不得不这多唠叨几句。</p>
<p>不瞒大家，做程序员之前俺也是个习武之人，扎马步、端棍子是每天不可缺少的一项基础功练习，无论是刮风还是下雨天，师傅就让你每天都要做同样的事情，习武前俺并不知道为什么让俺总练这些没有实际用途的东西。后来，俺在看《<strong>李小龙</strong>》这部电视剧中找到了答案，俺也将这几句话贴在了俺的 Github 仓库上，时时刻刻提醒着自己“基本功”的重要性！</p>
<ul>
<li><strong>练习“站桩”每天要坚持，一天都不能少！</strong></li>
<li><strong>练“武”不练“功”，到老一场空！</strong></li>
<li><strong>内练心智，外练筋骨！</strong></li>
<li><strong>再好的功夫，练不好基本功，也会走样！</strong></li>
<li><strong>练”武“太急是大忌，”基本功“要稳！</strong></li>
</ul>
<p>俺对自己总结的这几句话，在后来自学前端中对俺有很大的影响和感悟。俺这里不是强调俺功夫有多厉害（俺可以一个打一群的那种<del>），而是俺强调的是编程”基本功“的重要性，同时你我都应该重视起来</del></p>
<p>前端的基本功俺认为最重要的有以下几个：</p>
<ul>
<li><strong>HTML / CSS</strong></li>
<li><strong>JavaScript基础/进阶</strong> </li>
<li><strong>前端性能优化</strong></li>
<li><strong>网络原理</strong> </li>
<li><strong>设计模式</strong> </li>
<li><strong>数据结构与算法</strong> </li>
<li><strong>操作系统</strong></li>
</ul>
<p>很多人说，第一条“基本功”可以理解是重点，但是对于后边几个“基本功”，前端有必要深入学习吗？而且这三方面学习来比较枯燥、无趣，学了也不一定的在实际的业务中用到。可别这么想，上边的几个基本功都是可以提高你的“<strong>个人核心竞争力</strong>”，所谓的“个人核心竞争力”，所谓的核心竞争力就是别人大部分没有的能力，而你却有。除此之外，这些“基本功”可以更好你项目的业务逻辑（设计模式），提高项目功能的性能（数据结构与算法），优化提升网络的通信效率（网络原理）。最后，容俺多啰嗦一句，有些理论看似在实际开发项目中用不到，但是真的有必要知道，当你真正遇到该问题的时候，你能通过已知的理论能够够快速定位到该问题。</p>
<h4 id="2、思路是否清晰明确"><a href="#2、思路是否清晰明确" class="headerlink" title="2、思路是否清晰明确"></a>2、思路是否清晰明确</h4><p>相信很多小伙伴和俺一样，写代码有一个毛病，还没把整个程序的思路理清，就开始上手写代码。后来因为这种情况，俺吃了很多亏，所以现在几乎慢慢的改掉了这个坏习惯，可以说这是编程的大忌，尤其是在给企业做项目的时候，不仅造成企业项目中的损失也会造成个人时间上的损失。</p>
<p>确实有些简单的问题直接上手写代码也是没问题的，但是对于复杂的问题，就要求开发者的思路清晰明确，越是复杂，越是要求开发者具备这种能力。为了能够养成写代码前理清思路、写好文档的习惯，俺这里还是建议大家无论是简单问题还是复杂问题，在动手写代码之前一定要保证把思路清晰哦~</p>
<p>俺这里分享自己最实用的三种整理思路的方式，<strong>手写、画图、测试</strong>。</p>
<ul>
<li><strong>手写</strong></li>
</ul>
<p>通常一般拿到客户需求文档，显示用文字的形式去理一下整个项目的逻辑。如果在校生的话，一般会刷一些算法题，刷题之前一般都会将想到的思路写在纸上，然后选择最优的一个思路来进行测试程序的性能。自然而然这种先理清思路后写代码的习惯，在面试中也不用刻意的去表现了。</p>
<ul>
<li><strong>画图</strong></li>
</ul>
<p>除了将程序思路写下，另一种提倡的就是画图，画图更能够保持思路清晰的去解决问题。就拿俺经常用动画来讲解技术的经历，很多人看了动画以及制作的一些图，对整个程序的思路就立马有一个清晰的思路，一般在纸上大体画画就可以，如果追求画的美观，还是要下不少的功夫的~。</p>
<ul>
<li><strong>测试</strong></li>
</ul>
<p>最后一个方法就是将程序中的所有测试用例列出来，用于对你写的程序思路是否完善。当然，所有的测试用例不可能我们单纯的用大脑想全面的，这个方式有一定的局限性，可以结合手写、画图理清项目的设计思路。</p>
<h4 id="3、能否写高质量代码的能力"><a href="#3、能否写高质量代码的能力" class="headerlink" title="3、能否写高质量代码的能力"></a>3、能否写高质量代码的能力</h4><p>什么是高质量代码？如何写出高质量代码？都是我们要弄明白的问题。对于什么高质量的代码，俺的个人见解一下几个方面。</p>
<p>第一，程序中的一些边界条件是否考虑清楚。通常我们前期写代码都是 bug 百出，而这些 bug 正式考虑的不全面导致的。比如：上传表单按钮，你是否考虑到避免用户连续单击重复提交的情况？再如有输入框地方是否存在 XSS 攻击？虽然这些都是小细节，正式以为小细节，有时导致牵一发而动全身的威力。</p>
<p>第二，在面试中，面试官让你做一些典型的题目，一般你认为越是简单的越是容易，而的确相反，简单的题目越是有坑，作为面试者越是不会轻易的考虑到细节点。因为这道题在你心里的定位是道简单的题，你已经放松了警惕，给自己一个定心丸“不必多思考”。比如你是否判断输入的值是否为空，是否判断空指针的情况等等情况。面试者除了要求你完成一定的功能，还要求你是否注意一些细节问题。</p>
<p>回到问题的本质，俺这系列要讲的是如何应对面试，提高自己能力，提高个人核心竞争力以及日常开发中减少一些 bug。如何锻炼自己写高质量代码的能力才是俺重点要分享的。如下三个步骤：</p>
<ul>
<li><strong>将程序或者项目中的边界条件或者特殊条件考虑全面（并不能全部考虑到，主要靠项目中多积累）。</strong></li>
<li><strong>然后应对这些条件，列出要进行测试的例子。</strong></li>
<li><strong>写完代码，将测试用例带入，判断程序是否正确运行。</strong></li>
</ul>
<h4 id="4、是否有优化性能的能力"><a href="#4、是否有优化性能的能力" class="headerlink" title="4、是否有优化性能的能力"></a>4、是否有优化性能的能力</h4><p>一个优秀的程序员，对程序的性能优化也是追求极致的。面试过程中，面试官会通过前端常见的页面性能优化以及算法题来考察你的性能优化的能力。前端的性能优化主要在于网络（资源的压缩、合并）、渲染层面（首屏渲染）的优化。这里推荐一个俺看过的一本小册，这本小册让俺受益匪浅，就是阿里巴巴修言的《前端性能优化与原理实践》（PS：没广告费，是俺觉得好，才真心推荐给你们滴~）。</p>
<p>其次面试的时候，面试官对于前端页面的优化只在口头聊聊，作为面试官考察你的性能优化能力只能在手写算法方面了。要想对算法进行各个方面的优化，首先你需知道各个数据结构的优缺点以及对算法时间和空间效率的分析。</p>
<p>能够具备优化性能的能力，是每一个前端工程师日常中不可忽略的能力。</p>
<h4 id="5、是否有快速学习能力"><a href="#5、是否有快速学习能力" class="headerlink" title="5、是否有快速学习能力"></a>5、是否有快速学习能力</h4><p>世界在发展，技术在变更。适者生存，不适者淘汰。能否有快速学习的能力直接决定着你个人生存与淘汰。前端技术迭代更新飞速，从 ES5 到 ES6、ES7、ES8、ES9、ES10，再到 webpack 1.0、2.0、3.0、4.0 … </p>
<p>如果作为一个前端人员，只有具备良好的学习能力才能跟得上技术的迭代更新。通常面试中，面试官考察你的快速学习能力会问你平常怎么进行学习的？看书还是视频，还是开源社区？之所以很多的面试官反感培训机构出来的程序员，这个短期的培训，自主的学习能力是培养不出来的，而且培训机构目标是速成。但是，不能完全否定的，即便培训机构出的自学能力并不差，但是公司为了降低筛选优秀程序员成本，自然而且会非培训中筛选。</p>
<p>你会的编程语言多不代表学习能力就强。作为一个前端工程，如果你认为日常开发主要与 JS 打交道，包括以后的个人的技术发展，那就是大错特错了。编程语言无界限，学习各个编程语言设计的优点，才是我们学习的精髓所在。</p>
<p>著有牛B轰轰《Thinking in C++》和《Thinking in Java》的世界级别编程界的大牛 <code>Bruce Eckel</code>说过。</p>
<p><strong>“除非你准备活到老学到老，不然的话，不要进入这个行业！编程看起来似乎是一个高收入而又稳定的工作。但要做到这一点，唯一的途径是：始终让自己更有价值。你学得越深入，你就越有价值，也就意味着你有更好的职业前景，可以配得上更高的薪水”</strong>。</p>
<p>俺要说的是，怎么始终让自己有价值？那就是具备快速学习的能力才能使这个高薪的行业里始终有价值。</p>
<h4 id="6、是否有人际沟通能力"><a href="#6、是否有人际沟通能力" class="headerlink" title="6、是否有人际沟通能力"></a>6、是否有人际沟通能力</h4><p>给公司做项目和自己在学校折腾项目不一样，公司应聘你就是为了能够给公司产生利益。技术扎实是能够进入一家企业的必要条件而不能作为充分条件，除此之外还要求你具备其他的能力，如人际沟通能力，要说这个能力有过重要？就拿俺自身的例子来说吧，之前给一家企业做一个外包项目，就是因为前期沟通的过程中，理解错了客户的需求，导致后续所做的开发、测试、上线都是白做。</p>
<p>在公司也一样，一个项目团队没有沟通好，就开始下手写代码，造成一个公司损失，如果你是公司的领导，还会招聘沟通能力差的人吗？</p>
<p>那怎么提升自己的人际沟通能力？每个人的沟通能力都不一样，其实俺没有一个通用的方法，俺都是通过犯错，踩坑，反思进行提高的，如果你有更好的方式，欢迎来撩~</p>
<h4 id="7、是否具备强大的综合能力"><a href="#7、是否具备强大的综合能力" class="headerlink" title="7、是否具备强大的综合能力"></a>7、是否具备强大的综合能力</h4><p>本来是主要强调前六条，最一条综合能力是俺后期补充上的，俺认为和前六条同样的重要。俺不认为程序员和一个机器一样只会写代码，而是每一个程序员除了会写代码，而且要具备一些管理能力、领导能力、谈判的能力等等。有句话说的好，叫<strong>“技多不压身</strong>”，也就是一个人的综合能力要强，综合能力同样能提升你的个人核心竞争力。</p>
<p>很多人在谈程序员 35 岁危机，俺的观点和这个恰恰相反，35 岁应该是一个程序员最“光辉”的阶段，凭着程序员前期的学习能力，完全可以轻松掌握多个领域的知识，到了 35 岁虽然代码写不动了，你可以转你所感兴趣的领域，而这种领域的学习是你前期不断学习建立起来的。</p>
<p>举个常见的例子哈，据俺了解，很多公司为了让一些写不动代码的老员工开始往管理岗位转，但是出现一个问题就是，老板都推着你往管理岗位转，但是此时很多老员工并不具备管理的能力，因为他更习惯于用技术思考问题，以及强打不动的固执，不愿学习技术以外的知识，导致了肉都到了嘴边也吃不到的感觉。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>一开头俺就写了这么大的些，有些唠唠叨叨，但是俺认为这些唠唠叨叨的零碎内容也是构成这一系列的内容，就像炒菜，少一个配料，这菜就不香了。文章也是一样，少了这些就突然它不香了。之所以写成免费系列分享，就是为了不让俺自己在写作上受到一些条件限制，该写的一样不能少。我们开始进入下一个环节~</p>
</blockquote>



<h2 id="✏️面试前如何做准备？"><a href="#✏️面试前如何做准备？" class="headerlink" title="✏️面试前如何做准备？"></a>✏️面试前如何做准备？</h2><h3 id="一、简历准备"><a href="#一、简历准备" class="headerlink" title="一、简历准备"></a>一、简历准备</h3><p>简历是应聘者第一印象的展现，可以说我们见到一个陌生，首先看的是颜值（知道当年马云爸爸为什么每次应聘都失败了吧）。虽然一份简历并不能代表你的全部，但是作为给面试官的第一印象，很有必要好好斟酌的设计一下（重点在于内容部分），下面分享一下俺的经验。</p>
<h4 id="简历形式"><a href="#简历形式" class="headerlink" title="简历形式"></a>简历形式</h4><p>一份让 HR 看了能够眼前一亮的简历的前提是<strong>舒服、放松</strong>，毕竟每天 HR 看上百上千份简历，如果你的简历能够让  HR 翻到你的简历的时候，让她瞬间感觉你的简历无论是排版还是内容，与其他简历形成强烈的对比，那么大大增加了你下一步与面试官的机会。按个人认为，简历遵循一下几点，在形式上可以打败 50% 的应聘者了。</p>
<ul>
<li><strong>非统一简历</strong></li>
<li><strong>简约大气简历</strong></li>
<li><strong>真实简历</strong></li>
<li><strong>PDF 版本</strong></li>
</ul>
<h5 id="非统一简历"><a href="#非统一简历" class="headerlink" title="非统一简历"></a>非统一简历</h5><p>很过的招聘网站都提供同一的简历模板（Boos 直聘、拉勾招聘、实习僧等），正式因为简历形式的统一性，体现不出你简历让 HR 眼前一“亮”的感觉，没有对比是没有伤害的。通过实际的投递，也感觉出来了。俺之前在几个平台投了几百份简历，每次投递的时候都让你选择在线版还是附件简历，每次俺都提交错（在线版），往往根本没有几个 HR 来搭理你。后来俺发现了这个问题（一直投递的是在线简历），然后换成了自制的附件简历，果然找你沟通的 HR 也多了。</p>
<h5 id="简约大气"><a href="#简约大气" class="headerlink" title="简约大气"></a>简约大气</h5><p>很多小伙伴相信喜欢在简历网站下载一些模板，有些模板挺简约的，但是有的小伙伴确弄得简历样式花里胡哨，虽然在美学角度感觉起来设计的很不错。我们仔细想想，我们去展现的是自己的能力和技术，而不是在简历样式的设计上花里胡哨，有点说不过去了。简约、大气，给 HR 的印象让她关联到你也是属于这种类型的，属于简单、大气风格。</p>
<h5 id="真实简历"><a href="#真实简历" class="headerlink" title="真实简历"></a>真实简历</h5><p>简历写的内容一定真实，这个就不用俺多的强调了吧，毕竟“撒谎的孩子不是好孩子”。</p>
<h5 id="PDF-版本"><a href="#PDF-版本" class="headerlink" title="PDF 版本"></a>PDF 版本</h5><p>如果不是特别需要，使用 word 写简历就 OK，然后转化为 PDF 版本。对于为什么是 PDF 版本而不是其他版本，主要是因为 PDF 兼容性好，谁也不知道 HR 将会用什么软件打开你的简历，无论什么版本，你能保证你的简历在 HR 看的时候排版完好无损就行了。下面是俺之前简易版简历模板：（<strong>获取方式，公众号回复：「简历模板」</strong>）</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E7%AE%80%E5%8E%86%E6%A8%A1%E6%9D%BF.png" alt=""></p>
<h4 id="简历详情"><a href="#简历详情" class="headerlink" title="简历详情"></a>简历详情</h4><h5 id="简历页数"><a href="#简历页数" class="headerlink" title="简历页数"></a>简历页数</h5><p>简历的页数尽量控制在 1 ~ 2 页之间。</p>
<h5 id="个人闪光点"><a href="#个人闪光点" class="headerlink" title="个人闪光点"></a>个人闪光点</h5><p>如果每个人的简历都是差不多相同的，怎么才能让 HR 和面试官眼前一亮呢？那就是个人的闪光点，也就是要突出你的核心竞争力在哪？说白了，同样是应聘者，你具备什么大多数人不具备的能力能够让面试官给你发 offer 呢？很多人说，平常在学校最多参加个比赛做个小项目之类的，没有什么可以拿的出手的东西。那好，俺举例两点，给你作为一个参考，因为这两点在俺之前学习中观察身边的人以及在企业实习得出来的。</p>
<p><strong>1) 快速定位问题、解决问题的能力</strong></p>
<p>一般毕业生大部分缺少项目经验，从而定位问题和解决问题的能力相对于较弱的。如果你在校或者平常自己做项目，多善于总结的话，相信你定位问题和解决问题的能力一定比大部分人强。那么在招聘中，你可以通过项目突出这一闪光点。</p>
<p>而且大多数的应届毕业生刚实习的时候，一般遇到项目问题很难在短时间内搞定（分不同难度的问题），除了和他人请教之外，只能自己硬着头皮解决。一旦你有定位问题和快速解决问题的能力，那么在项目中会节省很多的时间去干别的事情。</p>
<p><strong>2) 规范编写代码的习惯</strong></p>
<p>很多自学者以及在校生，写代码就如流水账（俺也是），几乎没有什么好的编码习惯，来了需求就直接往上怼代码，导致项目后期扩展功能带来了不必要的麻烦和更多的 bug。现在的企业面临的难题就是软件的维护成本远远大于软件的开发成本，而且需求是客户一点点往上增加的，使得测试变的越来越困难。一个好的编码习惯，会在项目中大大减少不必要的开发和维护时间，从而使企业减少成本。对于如何规范写代码的习惯问题，还是要从小事做起~</p>
<h5 id="谨慎熟悉、精通关键字"><a href="#谨慎熟悉、精通关键字" class="headerlink" title="谨慎熟悉、精通关键字"></a>谨慎熟悉、精通关键字</h5><p>谨慎熟悉、精通、了解认识这几个简历中常用的关键词。很多人在面试中由于这几个关键字，吃了大亏，对，也包括俺自个。俺主要针对这几个关键字进行解释一下，分别对应自己知识技能如何填写。</p>
<ul>
<li><p><strong>精通：精通一词，不能轻易去写，写了就是给自己挖坑。</strong></p>
<p>那为什么还会有人去踩这个坑呢？不是说高人没有，是高人太少，之所有另外很多人写精通一词，是站在自己的认知角度去看待该领域，认为自己已经掌握了大部分的内容，但是，在面试官看来只不过是冰山一角。</p>
</li>
<li><p><strong>熟悉：简历中的大部分内容可以写熟悉某某技术项。</strong></p>
<p>我们在学校参加过比赛的项目或者自己做的一些项目，遇到的问题都是自己独立解决的，可以在简历中写“熟悉”某某技术。</p>
</li>
<li><p><strong>了解和认识：如果你只是知道和了解一些技术，看多一些文章或者书籍，并没有亲自实践过项目。</strong></p>
<p>简历中“了解和认识”这方面的内容少写，因为这代表你知道一些理论和表面上的知识。比如：了解 Node、TypeScript等。</p>
</li>
</ul>
<h5 id="项目经历"><a href="#项目经历" class="headerlink" title="项目经历"></a>项目经历</h5><p>项目经历可谓是面试中的一大重点，一个有着丰富的项目经历和一个项目经历没有的应聘者就是天差地别（天才除外）。但是往往有些毕业生没有项目经历，那这地方要空白吗？没有项目经历那就赶快去经历经历，去哪经历？俺推荐几种方式。</p>
<h5 id="如何找项目？"><a href="#如何找项目？" class="headerlink" title="如何找项目？"></a>如何找项目？</h5><ul>
<li><p><strong>Github 开源项目</strong></p>
<p>如果你想不但要有项目经历，而且希望项目高逼格，那么 Github 是首选。比如你要做一个 Vue 的项目，可以直接搜索 Vue，下方会搜索出来一些 Vue 相关的开源项目了，每个项目都会有详细说明。</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%90%9C%E7%B4%A2vue.png" alt=""></p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%90%9C%E7%B4%A2%E9%A1%B9%E7%9B%AE.png" alt=""></p>
</li>
<li><p><strong>免费资料</strong></p>
<p>如果你想看视频，世面上很多免费的视频资源（声明：拒绝盗版），比如很多公众号、开源社区等都可以获取到。实在找不到可以去俺公众号获取。搜索公众号「<strong>小鹿动画学编程</strong>」后台回复 “<strong>资源</strong>” 即可。</p>
</li>
</ul>
<ul>
<li><p><strong>付费视频</strong></p>
<p>如果一些免费的资源满足不了你，而且你不差钱，那么为了减少筛选的成本，可以去一些网站买一些付费类的课程看，俺前期的自学中也会买一些，毕竟时间很珍贵~</p>
</li>
</ul>
<h5 id="项目描述"><a href="#项目描述" class="headerlink" title="项目描述"></a>项目描述</h5><p>项目描述也是挺头疼的一件事，不知道从和说去，一有可能紧张导致思维逻辑有点乱了。看了网上都推荐 STAR 模型，那俺就拿来聊一聊。MBA智库百科介绍如下：</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>所谓STAR原则，即Situation（情景）、Task（任务）、Action（行动）和 Result（结果）四个英文单词的首字母组合。STAR原则是结构化面试当中非常重要的一个理论。</p>
</blockquote>



<p>面试官让你描述一个项目，可以在一下几个方面描述：</p>
<ul>
<li><p><strong>Situation(情景) —— 项目的背景</strong></p>
<p>开头可以给面试官简单的简述一下项目的开发背景，比如开发规模、开发需求、开发环境等。</p>
</li>
<li><p><strong>Task(任务)：—— 分配给你的任务</strong></p>
<p>这种重点，向面试官详细说明你在该项目中的任务，负责了哪一块。如果没有负责的地方就不要说了，因为面试官进一步对你做的地方详细的询问。</p>
</li>
<li><p><strong>Action(行动)：—— 你做了哪些事情</strong></p>
<p>这一部分是讲述如何完成分配给自己的任务的。比如你做了一个功能的页面，这个页面你是如何进行设计的？再比如，你做了数据库部分，你是如何设计数据库表的？</p>
</li>
<li><p><strong>Result(结果)：—— 你在项目中的贡献</strong></p>
<p>对于结果，可以详细说明一下，这里有个小技巧，什么时候用百分数什么时候用数字都是有讲究的。你说通过对页面的性能优化，首屏渲染提高了 20% 的速度。再比如，你在项目中解决了 8 个主要功能的 bug 等。</p>
</li>
</ul>
<p>​    </p>
<h5 id="项目闪光点"><a href="#项目闪光点" class="headerlink" title="项目闪光点"></a>项目闪光点</h5><p>对于以上的项目不能是流水账，应该突出你的个人核心竞争力，你在项目中解决了别人不能解决的问题，你做了哪些核心功能点，遇到难题又是如何进行解决的，都可以作为个人的闪光点。俺整理了一下几个方面，也欢迎文章下方留言补充哦~</p>
<ul>
<li><strong>项目遇到的问题是如何解决的？</strong></li>
<li><strong>从项目中学到了什么？</strong></li>
<li><strong>和团队成员有什么冲突？如何解决的？</strong></li>
</ul>
<h4 id="小技巧"><a href="#小技巧" class="headerlink" title="小技巧"></a>小技巧</h4><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>分享几个简历中的小技巧（欢迎留言补充哦~）。</p>
</blockquote>

<ul>
<li><strong>学校名称排版位置</strong></li>
</ul>
<p>如果你是某 985、211 的，学校的名字以及可以写在简历的开头，这样 HR 在筛选简历的时候，一眼看到你的学校名称（这个大家都知道，毕竟没有这么高的学历）。</p>
<p>如果你的学校和俺一样是野鸡大学，或者二本、三本之类的，可以将学校名称放在稍微靠后的位置，HR 第一眼会看到你的不是学校，而是你突出的能力。这样就会避免学校带来的缺陷（不能完全避免）。</p>
<ul>
<li><strong>最佳闪光点位置</strong></li>
</ul>
<p>简历中最显眼的地方应该写你的个人核心竞争力的内容，因为这样会让 HR 眼前一亮（一般在简历的中上位置）。而那些无关紧要，作为补充性的内容可以不写或者写在偏靠下的位置。</p>
<h4 id="大忌"><a href="#大忌" class="headerlink" title="大忌"></a>大忌</h4><ul>
<li><strong>切记不懂装懂；</strong></li>
<li><strong>切记胡编乱造；</strong></li>
<li><strong>切记夸大自己来展示自己能力；</strong></li>
<li><strong>切记列举一堆技能；</strong></li>
</ul>
<h3 id="二、了解公司"><a href="#二、了解公司" class="headerlink" title="二、了解公司"></a>二、了解公司</h3><p>面试前的简历我们写好了，但是收到面试通知之后，很多小伙伴收到面试邀请之后难免有些紧张，尤其是对于第一次准备面试的小伙伴来说。造成这种现象的原因无非就是心里没底，总是想面试的时候出现 “如果…怎么办….” 的状况或者是前期面试没有准备好，难免会担心面试出现各种紧急状况。</p>
<p>对于面试前的焦虑和紧张，也不是完全没有办法。在面试前。我们以先去了解这个公司，俺总结了一下几个方面。</p>
<ul>
<li><strong>面试内容</strong></li>
<li><strong>主要业务</strong></li>
<li><strong>发展前景</strong></li>
</ul>
<h4 id="1、面试内容"><a href="#1、面试内容" class="headerlink" title="1、面试内容"></a>1、面试内容</h4><p>有小伙伴要问俺了，一个公司的面试流程和内容可以知道吗？如果你非要这么问俺的话，俺的回答只能说是【间接的】。什么是间接？一般有很多网站可以查询该公司的相关信息，（比如：看准网），部分下面有些之前面试者面试后的感受以及对公司的评价之类的，那么所谓的间接，就是通过一些信息筛选出对你有用的信息。比如：</p>
<p>“面试官很 nice，整个面试面试官会照顾到面试者的感受…. “，再比如，</p>
<p>“当面试官问到原型链的时候，回答的有点含糊”</p>
<p>…</p>
<p>提取关键信息，首先面试官的态度很好的，所以你去这家公司面试不用很紧张；第二，这个面试者在这家公司面试的时候，被问到有关原型链的知识，如果换做我，是否能够准确的回答上来呢？</p>
<p>那么又有小伙伴问了，如果在这种网站查询不到相关的面试信息嗯？俺给你介绍另一个法子，那就是去搜索个人博客，现在很多的人喜欢记录自己的面试经历，直接百度或者谷歌也是 Ok 的。</p>
<p>虽然这个法子不是百分之百的能够帮助你，但是在面试前的准备上让你能够放松了些，因为你也该公司的面试流程或者内容有了大体的了解。</p>
<h4 id="2、主要业务产品"><a href="#2、主要业务产品" class="headerlink" title="2、主要业务产品"></a>2、主要业务产品</h4><blockquote>
<p>主要业务。最起码知道你来这个公司做什么产品和主要干什么吧？</p>
</blockquote>
<p>除了我们去了解该公司的面试流程和内容，还要去了解该公司的主要业务产品。公司招聘是双方互相选择的一个过程，而不是公司单方向选择你。那么问题来了，你这还没去面试呢。就需要提前了解该公司主要业务产品是干嘛的吗？当然，如果你不喜欢该公司的业务产，何必选择去面试呢？（单纯的体验一下面试的人除外~）</p>
<p>很多公司会在相关的网站列出自己公司的主要业务以及产品是干嘛的，难免也有与实际不否的地方，可以进一步提前准备好，在面试快结束的时候，来咨询一下面试官，公司的相关业务产品。</p>
<h4 id="3、发展前景"><a href="#3、发展前景" class="headerlink" title="3、发展前景"></a>3、发展前景</h4><blockquote>
<p>再一个就是了解该公司的发展前景，和你个人的爱好以及个人价值是否一致呢。</p>
</blockquote>
<p>互联网公司覆盖的领域很广，医疗领域、教育领域、娱乐领域、游戏领域等等。俺把其公司作为两种分类，一类是产品公司，这一类主要是针对特定的用户进行开发产品的，比如某公司主要对于医院来开发医疗系统。另一类呢是互联网公司。主要是面向大众化的产品，比如抖音、今日头条、微信等。当然，不同类型的公司对应的开发也是不一样的，俺就不在这展开说了。</p>
<h2 id="JavaScript-基础知识点"><a href="#JavaScript-基础知识点" class="headerlink" title="JavaScript 基础知识点"></a>JavaScript 基础知识点</h2><h3 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h3><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 JavaScript 中的基本类型有哪些？以及各个数据类型是如何存储的？</p>
</blockquote>

<p><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">javaScript</code> 的数据类型包括<span style="color:#ff502c;font-weight:bold;padding:0 2px">原始类型</span>和<span style="color:#ff502c;font-weight:bold;padding:0 2px">引用类型(对象类型)</span>。</p>
<p>原始类型包括以下 6 个：</p>
<ul>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">String</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Number</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Boolean</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">null</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">undefined</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Symbol</code></li>
</ul>
<p>引用类型统称为 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Object</code> 类型，如果细分的话，分为以下 5 个：</p>
<ul>
<li><code>Object</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Array</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Date</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">RegExp</code></li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Function</code></li>
</ul>
<h4 id="1、数据类型的存储形式"><a href="#1、数据类型的存储形式" class="headerlink" title="1、数据类型的存储形式"></a>1、数据类型的存储形式</h4><blockquote>
<p>栈（Stack）和堆（Heap），是两种基本的数据结构。Stack 在内存中自动分配内存空间的；Heap 在内存中动态分配内存空间的，不一定会自动释放。一般我们在项目中将对象类型手动置为 null 原因，减少无用内存消耗。</p>
</blockquote>
<p>​    </p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E5%A0%86%E5%92%8C%E6%A0%88%E5%86%85%E5%AD%98.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E5%A0%86%E5%92%8C%E6%A0%88%E5%86%85%E5%AD%98.png"></p>
<p>原始类型是按值形式存放在<strong>栈</strong>中的数据段，内存空间可以自由分配，同时可以<strong>按值直接访问</strong>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">var</span> b = a;</span><br><span class="line">b = <span class="number">30</span>;</span><br><span class="line"><span class="built_in">console</span>.log(a); <span class="comment">// 10值</span></span><br><span class="line"><span class="built_in">console</span>.log(b); <span class="comment">// 30值</span></span><br></pre></td></tr></table></figure>

<p>过程图示：</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E6%A0%88%E5%8F%98%E9%87%8F%E5%A4%8D%E5%88%B6.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E6%A0%88%E5%8F%98%E9%87%8F%E5%A4%8D%E5%88%B6.png"></p>
<p>引用类型是存放在<strong>堆</strong>内存中，每个对象在堆内存中有一个引用地址，就像是每个房间都有一个房间号一样。引用类型在栈中保存的就是这个对象在堆内存的引用地址，我们所说的“房间号”。通过“房间号”可以快速查找到保存在堆内存的对象。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj1 = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line"><span class="keyword">var</span> obj2 = obj1;</span><br><span class="line">obj2.name = <span class="string">"小鹿"</span>;</span><br><span class="line"><span class="built_in">console</span>.log(obj1.name); <span class="comment">// 小鹿</span></span><br></pre></td></tr></table></figure>

<p>过程图示：</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E5%AF%B9%E8%B1%A1%E5%A4%8D%E5%88%B6.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/%E5%AF%B9%E8%B1%A1%E5%A4%8D%E5%88%B6.png"></p>
<h4 id="2、Null"><a href="#2、Null" class="headerlink" title="2、Null"></a>2、Null</h4><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：为什么 typeof null 等于 Object?</p>
</blockquote>

<p>不同的对象在底层原理的存储是用二进制表示的，在 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">javaScript</code>中，如果二进制的前三位都为 0 的话，系统会判定为是 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Object</code>类型。<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">null</code>的存储二进制是 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">000</code>，也是前三位，所以系统判定 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">null</code>为 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Object</code>类型。</p>
<p><strong>扩展：</strong></p>
<p>这个 bug 个第一版的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">javaScript</code>留下来的。俺也进行扩展一下其他的几个类型标志位：</p>
<ul>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">000</code>：对象类型。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">1</code>：整型，数据是31位带符号整数。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">010</code>：双精度类型，数据是双精度数字。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">100</code>：字符串，数据是字符串。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">110</code>：布尔类型，数据是布尔值。</li>
</ul>
<h4 id="3、数据类型的判断"><a href="#3、数据类型的判断" class="headerlink" title="3、数据类型的判断"></a>3、数据类型的判断</h4><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：typeof 与 instanceof 有什么区别？</p>
</blockquote>

<p><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">typeof</code> 是一元运算符，同样返回一个字符串类型。一般用来判断一个变量是否为空或者是什么类型。</p>
<p>除了 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">null</code> 类型以及  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Object</code> 类型不能准确判断外，其他数据类型都可能返回正确的类型。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typeof</span> <span class="literal">undefined</span> <span class="comment">// 'undefined'</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="string">'10'</span>      <span class="comment">// 'String'</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="number">10</span>        <span class="comment">// 'Number'</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="literal">false</span>     <span class="comment">// 'Boolean'</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">Symbol</span>()  <span class="comment">// 'Symbol'</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">Function</span>  <span class="comment">// ‘function'</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="literal">null</span>		 <span class="comment">// ‘Object’</span></span><br><span class="line"><span class="keyword">typeof</span> []        <span class="comment">// 'Object'</span></span><br><span class="line"><span class="keyword">typeof</span> &#123;&#125;        <span class="comment">// 'Object'</span></span><br></pre></td></tr></table></figure>

<p>既然 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">typeof</code> 对对象类型都返回 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Object</code> 类型情况的局限性，我们可以使用 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">instanceof</code> 来进行判断<strong>某个对象是不是另一个对象的实例</strong>。返回值的是一个布尔类型。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [];</span><br><span class="line"><span class="built_in">console</span>.log(a <span class="keyword">instanceof</span> <span class="built_in">Array</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">instanceof</code>  运算符用来测试一个对象在其原型链中是否存在一个构造函数的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">prototype</code> 属性，如果对原型链不怎能了解，后边俺会具体的写到，这里大体记一下就 OK。</p>
<p>我们再测一下 ES6 中的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">class</code> 语法糖是什么类型。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;&#125;</span><br><span class="line"><span class="built_in">console</span>.log(A <span class="keyword">instanceof</span> <span class="built_in">Function</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>注意：原型链中的<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">prototype</code> 随时可以被改动的，改变后的值可能不存在于 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">object</code>的原型链上，<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">instanceof</code>返回的值可能就返回 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">false</code>。</p>
</blockquote>
<h4 id="4、类型转换"><a href="#4、类型转换" class="headerlink" title="4、类型转换"></a>4、类型转换</h4><p>类型转换通常在面试笔试中出现的比较多，对于类型转换的一些细节应聘者也是很容易忽略的，所以俺整理的尽量系统一些。<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">javaScript</code>是一种弱类型语言，变量不受类型限制，所以在特定情况下我们需要对类型进行转换。</p>
<p>「类型转换」分为<span style="color:#ff502c;font-weight:bold;padding:0 2px">显式类型转换</span>和<span style="color:#ff502c;font-weight:bold;padding:0 2px">隐式类型转换</span>。每种转换又分为<span style="color:#ff502c;font-weight:bold;padding:0 2px">原始类型转换</span>和<span style="color:#ff502c;font-weight:bold;padding:0 2px">对象类型转换</span>。</p>
<h5 id="显式类型转换"><a href="#显式类型转换" class="headerlink" title="显式类型转换"></a>显式类型转换</h5><p>显式类型转换就是我们所说强制类型转换。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>笔试题：其他数据类型转字符串类型！</p>
</blockquote>

<p>对于原始类型来说，转字符串类型会默认调用 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">toString()</code> 方法。</p>
<table>
<thead>
<tr>
<th align="left">数据类型</th>
<th align="left">String类型</th>
</tr>
</thead>
<tbody><tr>
<td align="left">数字</td>
<td align="left">转化为数字对应的字符串</td>
</tr>
<tr>
<td align="left">true</td>
<td align="left">转化为字符串 “true”</td>
</tr>
<tr>
<td align="left">null</td>
<td align="left">转化为字符串 “null”</td>
</tr>
<tr>
<td align="left">undefined</td>
<td align="left">转化为字符串 “undefined”</td>
</tr>
<tr>
<td align="left">Object</td>
<td align="left">转化为 “[object Object]”</td>
</tr>
</tbody></table>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">String</span>(<span class="number">123</span>);      <span class="comment">// "123"</span></span><br><span class="line"><span class="built_in">String</span>(<span class="literal">true</span>);     <span class="comment">// "true"</span></span><br><span class="line"><span class="built_in">String</span>(<span class="literal">null</span>);     <span class="comment">// "null"</span></span><br><span class="line"><span class="built_in">String</span>(<span class="literal">undefined</span>);<span class="comment">// "undefined"</span></span><br><span class="line"><span class="built_in">String</span>([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])   <span class="comment">// "1,2,3"</span></span><br><span class="line"><span class="built_in">String</span>(&#123;&#125;);		  <span class="comment">// "[object Object]"</span></span><br></pre></td></tr></table></figure>



<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>笔试题：其他数据类型转布尔类型！</p>
</blockquote>

<p>除了特殊的几个值 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">‘’</code>、 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">undefined</code>、 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">NAN</code>、 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">null</code>、 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">false</code>、 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">0</code>  转化为 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Boolean</code> 为 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">false</code> 之外，其他类型值都转化为 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">true</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Boolean</span>(<span class="string">''</span>)         <span class="comment">// false</span></span><br><span class="line"><span class="built_in">Boolean</span>(<span class="literal">undefined</span>)  <span class="comment">// false</span></span><br><span class="line"><span class="built_in">Boolean</span>(<span class="literal">null</span>)       <span class="comment">// false</span></span><br><span class="line"><span class="built_in">Boolean</span>(<span class="literal">NaN</span>)        <span class="comment">// false</span></span><br><span class="line"><span class="built_in">Boolean</span>(<span class="literal">false</span>)      <span class="comment">// false</span></span><br><span class="line"><span class="built_in">Boolean</span>(<span class="number">0</span>)          <span class="comment">// false</span></span><br><span class="line"><span class="built_in">Boolean</span>(&#123;&#125;)		    <span class="comment">// true</span></span><br><span class="line"><span class="built_in">Boolean</span>([])		    <span class="comment">// true</span></span><br></pre></td></tr></table></figure>



<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
        <p>笔试题：转化为数字类型！</p>
</blockquote>

<table>
<thead>
<tr>
<th align="left">数据类型</th>
<th align="left">数字类型</th>
</tr>
</thead>
<tbody><tr>
<td align="left">字符串</td>
<td align="left">1) 数字转化为对应的数字<br />2) 其他转化为 NaN</td>
</tr>
<tr>
<td align="left">布尔类型</td>
<td align="left">1) true 转化为 1<br />2) false 转化为 0</td>
</tr>
<tr>
<td align="left">null</td>
<td align="left">0</td>
</tr>
<tr>
<td align="left">undefined</td>
<td align="left">NaN</td>
</tr>
<tr>
<td align="left">数组</td>
<td align="left">1) 数组为空转化为 0；<br />2) 数组只有一个元素转化为对应元素；<br />3) 其他转化为NaN</td>
</tr>
<tr>
<td align="left">空字符串</td>
<td align="left">0</td>
</tr>
</tbody></table>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Number</span>(<span class="number">10</span>);        <span class="comment">// 10 </span></span><br><span class="line"><span class="built_in">Number</span>(<span class="string">'10'</span>);      <span class="comment">// 10 </span></span><br><span class="line"><span class="built_in">Number</span>(<span class="literal">null</span>);      <span class="comment">// 0  </span></span><br><span class="line"><span class="built_in">Number</span>(<span class="string">''</span>);        <span class="comment">// 0  </span></span><br><span class="line"><span class="built_in">Number</span>(<span class="literal">true</span>);      <span class="comment">// 1  </span></span><br><span class="line"><span class="built_in">Number</span>(<span class="literal">false</span>);     <span class="comment">// 0  </span></span><br><span class="line"><span class="built_in">Number</span>([]);        <span class="comment">// 0 </span></span><br><span class="line"><span class="built_in">Number</span>([<span class="number">1</span>,<span class="number">2</span>]);     <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">Number</span>(<span class="string">'10a'</span>);     <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">Number</span>(<span class="literal">undefined</span>); <span class="comment">// NaN</span></span><br></pre></td></tr></table></figure>



<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>笔试题：对象类型转原始类型！</p>
</blockquote>

<p>对象类型在转原始类型的时候，会调用内置的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">valueOf()</code>和 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">toString()</code> 方法，这两个方法是可以进行重写的。</p>
<p>转化原始类型分为两种情况：转化为<span style="color:#ff502c;font-weight:bold;padding:0 2px">字符串类型</span>或<span style="color:#ff502c;font-weight:bold;padding:0 2px">其他原始类型</span>。</p>
<ul>
<li>如果已经是原始类型，不需要再进行转化。</li>
<li>如果转字符串类型，就调用内置函数中的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">toString()</code>方法。</li>
<li>如果是其他基本类型，则调用内置函数中的  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">valueOf()</code>方法。</li>
<li>如果返回的不是原始类型，则会继续调用 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">toString()</code> 方法。</li>
<li>如果还没有返回原始类型，则报错。</li>
</ul>
<h4 id="5、四则运算"><a href="#5、四则运算" class="headerlink" title="5、四则运算"></a>5、四则运算</h4><p>隐士类型转化是不需要认为的强制类型转化，<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">javaScript</code> 自动将类型转化为需要的类型，所以称之为隐式类型转换。</p>
<h5 id="加法运算"><a href="#加法运算" class="headerlink" title="加法运算"></a>加法运算</h5><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>加法运算符是在运行时决定，到底是执行相加，还是执行连接。运算数的不同，导致了不同的语法行为，这种现象称为“重载”。</p>
</blockquote>

<ul>
<li>如果双方都不是字符串，则将转化为<strong>数字</strong>或<strong>字符串</strong>。<ul>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Boolean + Boolean</code>会转化为数字相加。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Boolean + Number</code> 布尔类型转化为数字相加。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Object + Number</code> 对象类型调用 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">valueOf</code>，如果不是 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">String、Boolean</code>或者 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Number</code>类型，则继续调用 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">toString()</code>转化为字符串。</li>
</ul>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">true</span> + <span class="literal">true</span>  <span class="comment">// 2</span></span><br><span class="line"><span class="number">1</span> + <span class="literal">true</span>     <span class="comment">// 2</span></span><br><span class="line">[<span class="number">1</span>] + <span class="number">3</span>      <span class="comment">// '13'</span></span><br></pre></td></tr></table></figure>

<ul>
<li>字符串和字符串以及字符串和非字符串相加都会进行<strong>连接</strong>。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> + <span class="string">'b'</span>     <span class="comment">// ‘1b’</span></span><br><span class="line"><span class="literal">false</span> + <span class="string">'b'</span> <span class="comment">// ‘falseb’</span></span><br></pre></td></tr></table></figure>



<h5 id="其他运算"><a href="#其他运算" class="headerlink" title="其他运算"></a>其他运算</h5><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>其他算术运算符（比如减法、除法和乘法）都不会发生重载。它们的规则是：所有运算子一律转为数值，再进行相应的数学运算。</p>
</blockquote>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> * <span class="string">'2'</span>  <span class="comment">// 2</span></span><br><span class="line"><span class="number">1</span> * []   <span class="comment">// 0</span></span><br></pre></td></tr></table></figure>



<h4 id="6、逻辑运算符"><a href="#6、逻辑运算符" class="headerlink" title="6、逻辑运算符"></a>6、逻辑运算符</h4><p>逻辑运算符包括两种情况，分别为<span style="color:#ff502c;font-weight:bold;padding:0 2px">条件判断</span>和<span style="color:#ff502c;font-weight:bold;padding:0 2px">赋值操作</span>。</p>
<p><strong>条件判断</strong></p>
<ul>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">&&</code> ：所有条件为真，整体才为真。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">||</code> ：只有一个条件为真，整体就为真。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">true</span> &amp;&amp; <span class="literal">true</span>   <span class="comment">// true</span></span><br><span class="line"><span class="literal">true</span> &amp;&amp; <span class="literal">false</span>  <span class="comment">// false</span></span><br><span class="line"><span class="literal">true</span> || <span class="literal">true</span>   <span class="comment">// true</span></span><br><span class="line"><span class="literal">true</span> || <span class="literal">false</span>  <span class="comment">// true</span></span><br></pre></td></tr></table></figure>



<p><strong>赋值操作</strong></p>
<ul>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A && B</code></li>
</ul>
<p>首先看 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code> 的真假， <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code> 为假，返回  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code> 的值， <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code>  为真返回  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">B</code>  的值。（不管 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">B</code> 是啥）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="number">0</span> &amp;&amp; <span class="number">1</span>) <span class="comment">// 0</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">1</span> &amp;&amp; <span class="number">2</span>) <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<ul>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A || B</code></li>
</ul>
<p>首先看  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code>  的真假， <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code> 为真返回的是  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code>  的值， <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">A</code>  为假返回的是  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">B</code>  的值（不管 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">B</code>  是啥）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="number">0</span> || <span class="number">1</span>) <span class="comment">// 1</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">1</span> || <span class="number">2</span>) <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>



<h4 id="7、比较运算符"><a href="#7、比较运算符" class="headerlink" title="7、比较运算符"></a>7、比较运算符</h4><p>比较运算符在逻辑语句中使用，以判定变量或值是否相等。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：== 和 === 的区别？</p>
</blockquote>

<p>对于 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">===</code> 来说，是严格意义上的相等，会比较两个操作符的类型和值。</p>
<ul>
<li>如果 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">X</code> 和  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Y</code> 的类型不同，返回  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">false</code> ；</li>
<li>如果 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">X</code> 和  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Y</code> 的类型相同，则根据下方表格进一步判断</li>
</ul>
<table>
<thead>
<tr>
<th>条件</th>
<th>例子</th>
<th>返回值</th>
</tr>
</thead>
<tbody><tr>
<td>undefined === undefined</td>
<td>undefined === undefined</td>
<td>true</td>
</tr>
<tr>
<td>null === null</td>
<td>null === null</td>
<td>true</td>
</tr>
<tr>
<td>String === String<br />(当字符串顺序和字符完全相等的时候返回 true，否则返回 false)</td>
<td>‘a’ === ‘a’<br />‘a’ === ‘aa’</td>
<td>true<br />false</td>
</tr>
<tr>
<td>Boolean  === Boolean</td>
<td>true === true<br />true === false</td>
<td>true<br />false</td>
</tr>
<tr>
<td>Symbol === Symbol</td>
<td>相同的 Symbol 返回 true，<br />不相同的 Symbol 返回 false</td>
<td></td>
</tr>
<tr>
<td>Number  === Number<br />① 其中一个为 NaN，返回 false<br />② X 和 Y 值相等，返回 true<br />③ 0 和 -0，返回 true<br />④ 其他返回 false</td>
<td>NaN ==== NaN<br />NaN === 1<br />3 === 3<br />+0 === -0<br /></td>
<td>false<br />false<br />true<br />true</td>
</tr>
</tbody></table>
<p>而对于 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">==</code>来说，是非严格意义上的相等，先判断两个操作符的类型是否相等，如果类型不同，则先进行类型转换，然后再判断值是否相等。</p>
<ul>
<li>如果 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">X</code> 和  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Y</code> 的类型相同，返回  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">X == Y</code>  的比较结果；</li>
<li>如果  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">X</code> 和 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">Y</code> 的类型不同，根据下方表格进一步判断;</li>
</ul>
<table>
<thead>
<tr>
<th>条件</th>
<th>例子</th>
<th>返回值</th>
</tr>
</thead>
<tbody><tr>
<td>null == undefined</td>
<td>null == undefined</td>
<td>true</td>
</tr>
<tr>
<td>String == Number，String  转 Number</td>
<td>‘2’ == 2</td>
<td>true</td>
</tr>
<tr>
<td>Boolean == Number，Boolean 转 Number</td>
<td>true == 1</td>
<td>true</td>
</tr>
<tr>
<td>Object == String,Number,Symbol，将 Object 转化为原始类型再比较值大小</td>
<td>[1] == 1<br />[1] == ‘1’</td>
<td>true<br />true</td>
</tr>
<tr>
<td>其他返回 false</td>
<td></td>
<td>false</td>
</tr>
</tbody></table>
<h3 id="this"><a href="#this" class="headerlink" title="this"></a>this</h3><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是 this 指针?以及各种情况下的 this 指向问题。</p>
</blockquote>

<p><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>就是一个对象。不同情况下 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>指向的不同，有以下几种情况，（希望各位亲自测试一下，这样会更容易弄懂）：</p>
<ul>
<li>对象调用，<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code> 指向该对象（前边谁调用 this 就指向谁）。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    name:<span class="string">'小鹿'</span>,</span><br><span class="line">    age: <span class="string">'21'</span>,</span><br><span class="line">    print: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="keyword">this</span>)</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="keyword">this</span>.name + <span class="string">':'</span> + <span class="keyword">this</span>.age)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过对象的方式调用函数</span></span><br><span class="line">obj.print();        <span class="comment">// this 指向 obj</span></span><br></pre></td></tr></table></figure>



<ul>
<li>直接调用的函数，<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>指向的是全局 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">window</code>对象。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">print</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">	<span class="built_in">console</span>.log(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 全局调用函数</span></span><br><span class="line">print();   <span class="comment">// this 指向 window</span></span><br></pre></td></tr></table></figure>



<ul>
<li>通过 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">new</code>的方式，<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>永远指向新创建的对象。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name = name;</span><br><span class="line">    <span class="keyword">this</span>.age = age;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> xiaolu = <span class="keyword">new</span> Person(<span class="string">'小鹿'</span>,<span class="number">22</span>);  <span class="comment">// this = &gt; xaiolu</span></span><br></pre></td></tr></table></figure>



<ul>
<li>箭头函数中的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>。</li>
</ul>
<p>由于箭头函数没有单独的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>值。箭头函数的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>与声明所在的上下文相同。也就是说调用箭头函数的时候，不会隐士的调用 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>参数，而是从定义时的函数继承上下文。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;</span><br><span class="line">    a:<span class="function"><span class="params">()</span>=&gt;</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 对象调用箭头函数</span></span><br><span class="line">obj.a(); <span class="comment">// window</span></span><br></pre></td></tr></table></figure>



<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：如何改变 this 的指向？</p>
</blockquote>

<p>我们可以通过调用函数的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">call、apply、bind</code> 来改变 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>的指向。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    name:<span class="string">'小鹿'</span>,</span><br><span class="line">    age:<span class="string">'22'</span>,</span><br><span class="line">    adress:<span class="string">'小鹿动画学编程'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">print</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="keyword">this</span>);       <span class="comment">// 打印 this 的指向</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="built_in">arguments</span>);  <span class="comment">// 打印传递的参数</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过 call 改变 this 指向</span></span><br><span class="line">print.call(obj,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>);   </span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过 apply 改变 this 指向</span></span><br><span class="line">print.apply(obj,[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过 bind 改变 this 的指向</span></span><br><span class="line"><span class="keyword">let</span> fn = print.bind(obj,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>);</span><br><span class="line">fn();</span><br></pre></td></tr></table></figure>

<p>对于基本的使用想必各位小伙伴都能掌握，俺就不多废话，再说一说这三者的共同点和不同点。</p>
<p><strong>共同点：</strong></p>
<ul>
<li>三者都能改变 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>指向，且第一个传递的参数都是 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>指向的对象。</li>
<li>三者都采用的后续传参的形式。</li>
</ul>
<p><strong>不同点：</strong></p>
<ul>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">call</code> 的传参是单个传递的（试了下数组，也是可以的），而 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">apply</code> 后续传递的参数是<strong>数组形式（传单个值会报错）</strong>，而 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">bind</code> 没有规定，传递值和数组都可以。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">call</code> 和 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">apply</code> 函数的执行是直接执行的，而 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">bind</code> 函数会返回一个函数，然后我们想要调用的时候才会执行。</li>
</ul>
<blockquote>
<p>扩展：如果我们使用上边的方法改变箭头函数的 this 指针，会发生什么情况呢？能否进行改变呢？</p>
</blockquote>
<p>由于箭头函数没有自己的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code> 指针，通过 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">call()</code> 或 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">apply()</code> 方法调用一个函数时，只能传递参数（不能绑定  <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">this</code>），他们的第一个参数会被忽略。</p>
<h3 id="new"><a href="#new" class="headerlink" title="new"></a>new</h3><p>对于 <code>new</code> 关键字，我们第一想到的就是在面向对象中 <code>new</code> 一个实例对象，但是在 JS 中的 <code>new</code> 和 <code>Java</code> 中的 <code>new</code> 的机制不一样。</p>
<p>一般 <code>Java</code> 中，声明一个<code>构造函数</code>，通过 <code>new 类名()</code> 来创建一个实例，而这个<code>构造函数</code> 是一种特殊的函数。但是在 <code>JS</code> 中，只要 <code>new</code> 一个函数，就可以 new 一个对象，函数和构造函数没有任何的区别。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：new 内部发生了什么过程？可不可以手写实现一个 new 操作符？</p>
</blockquote>

<p><code>new</code> 的过程包括以下四个阶段：</p>
<ul>
<li>创建一个新对象。</li>
<li>这个新对象的 <code>__proto__</code> 属性指向原函数的 <code>prototype</code> 属性。(即继承原函数的原型)</li>
<li>将这个新对象绑定到 此函数的 <code>this</code> 上 。</li>
<li>返回新对象，如果这个函数没有返回其他对象。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// new 生成对象的过程</span></span><br><span class="line"><span class="comment">// 1、生成新对象</span></span><br><span class="line"><span class="comment">// 2、链接到原型</span></span><br><span class="line"><span class="comment">// 3、绑定 this</span></span><br><span class="line"><span class="comment">// 4、返回新对象</span></span><br><span class="line"><span class="comment">// 参数：</span></span><br><span class="line"><span class="comment">// 1、Con: 接收一个构造函数</span></span><br><span class="line"><span class="comment">// 2、args：传入构造函数的参数</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">create</span>(<span class="params">Con, ...args</span>)</span>&#123;</span><br><span class="line">    <span class="comment">// 创建空对象</span></span><br><span class="line">    <span class="keyword">let</span> obj = &#123;&#125;;</span><br><span class="line">    <span class="comment">// 设置空对象的原型(链接对象的原型)</span></span><br><span class="line">    obj._proto_ = Con.prototype;</span><br><span class="line">    <span class="comment">// 绑定 this 并执行构造函数(为对象设置属性)</span></span><br><span class="line">    <span class="keyword">let</span> result = Con.apply(obj,args)</span><br><span class="line">    <span class="comment">// 如果 result 没有其他选择的对象，就返回 obj 对象</span></span><br><span class="line">    <span class="keyword">return</span> result <span class="keyword">instanceof</span> <span class="built_in">Object</span> ?  result : obj;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 构造函数</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Test</span>(<span class="params">name, age</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name = name</span><br><span class="line">    <span class="keyword">this</span>.age = age</span><br><span class="line">&#125;</span><br><span class="line">Test.prototype.sayName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="keyword">this</span>.name)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 实现一个 new 操作符</span></span><br><span class="line"><span class="keyword">const</span> a = create(Test,<span class="string">'小鹿'</span>,<span class="string">'23'</span>)</span><br><span class="line"><span class="built_in">console</span>.log(a.age)</span><br></pre></td></tr></table></figure>

<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：有几种创建对象的方式，字面量相对于 new 创建对象有哪些优势？</p>
</blockquote>

<p>最常用的创建对象的两种方式：</p>
<ul>
<li>*<em>new 构造函数  *</em></li>
<li><strong>字面量</strong></li>
</ul>
<p>其他创建对象的方式：</p>
<ul>
<li><strong>Object.create()</strong></li>
</ul>
<p>字面量创建对象的优势所在：</p>
<ul>
<li>代码量更少，更易读</li>
<li>对象字面量运行速度更快，它们可以在解析的时候被优化。他不会像 <code>new</code> 一个对象一样，解析器需要顺着作用域链从当前作用域开始查找，如果在当前作用域找到了名为 <code>Object()</code> 的函数就执行，如果没找到，就继续顺着作用域链往上照，直到找到全局 <code>Object()</code> 构造函数为止。</li>
<li><code>Object()</code> 构造函数可以接收参数，通过这个参数可以把对象实例的创建过程委托给另一个内置构造函数，并返回另外一个对象实例，而这往往不是你想要的。</li>
</ul>
<p>对于 <code>Object.create()</code>方式创建对象：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.create(proto, [propertiesObject]);</span><br></pre></td></tr></table></figure>

<ul>
<li><code>proto：</code>新创建对象的原型对象。</li>
<li><code>propertiesObject：</code>（可选）可为创建的新对象设置属性和值。</li>
</ul>
<p>一般用于继承：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> People = <span class="function"><span class="keyword">function</span> (<span class="params">name</span>)</span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.name = name;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">People.prototype.sayName = <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="keyword">this</span>.name);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age</span>)</span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.age = age;</span><br><span class="line">  People.call(<span class="keyword">this</span>, name);  <span class="comment">// 使用call，实现了People属性的继承</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用Object.create()方法，实现People原型方法的继承，并且修改了constructor指向</span></span><br><span class="line">Person.prototype = <span class="built_in">Object</span>.create(People.prototype, &#123;</span><br><span class="line">  <span class="keyword">constructor</span>: &#123;</span><br><span class="line">    configurable: <span class="literal">true</span>,</span><br><span class="line">    enumerable: <span class="literal">true</span>,</span><br><span class="line">    value: Person,</span><br><span class="line">    writable: <span class="literal">true</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">Person.prototype.sayAge = <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="keyword">this</span>.age);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> p1 = <span class="keyword">new</span> Person(<span class="string">'person1'</span>, <span class="number">25</span>);</span><br><span class="line"> </span><br><span class="line">p1.sayName();  <span class="comment">//'person1'</span></span><br><span class="line">p1.sayAge();   <span class="comment">//25</span></span><br></pre></td></tr></table></figure>

<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：new/字面量 与 Object.create(null) 创建对象的区别？</p>
</blockquote>

<ul>
<li><code>new</code> 和 字面量创建的对象的原型指向 <code>Object.prototype</code>，会继承 <code>Object</code> 的属性和方法。</li>
<li>而通过 <code>Object.create(null)</code> 创建的对象，其原型指向 <code>null</code>，<code>null</code> 作为原型链的顶端，没有也不会继承任何属性和方法。</li>
</ul>
<h3 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h3><p>闭包面试中的重点，但是对于很多初学者来说都是懵懵的，所以俺就从最基础的作用域讲起，大佬请绕过。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是作用域？什么是作用域链？</p>
</blockquote>

<p>规定<span style="color:#ff502c;font-weight:bold;padding:0 2px">变量和函数</span>的可使用范围叫做作用域。只看定义，挺抽象的，举个例子::chestnut:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> a = <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> b = <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>声明两个函数，分别创建量两个私有的作用域（可以理解为两个封闭容器），<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">fn2</code> 是不能直接访问私有作用域 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">fn1</code> 的变量 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">a</code> 的。同样的，在 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">fn1</code> 中不能访问到 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">fn2</code> 中的 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">b</code> 变量的。一个函数就是一个作用域。</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E9%97%AD%E5%8C%85/%E7%A7%81%E6%9C%89%E4%BD%9C%E7%94%A8%E5%9F%9F.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E9%97%AD%E5%8C%85/%E7%A7%81%E6%9C%89%E4%BD%9C%E7%94%A8%E5%9F%9F.png"></p>
<p>每个函数都会有一个作用域，查找变量或函数时，由局部作用域到全局作用域依次查找，<span style="color:#ff502c;font-weight:bold;padding:0 2px">这些作用域的集合就称为作用域链。</span> 如果还不是很好理解，俺再举个例子​：:chestnut:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">1</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">fn1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="function"><span class="keyword">function</span> <span class="title">fn2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">            <span class="keyword">let</span> c = <span class="number">3</span>;</span><br><span class="line">            <span class="built_in">console</span>.log(a);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 执行 fn2</span></span><br><span class="line">        fn2();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 执行 fn1</span></span><br><span class="line">    fn1();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 执行函数</span></span><br><span class="line">fn();</span><br></pre></td></tr></table></figure>

<p>虽然上边看起来嵌套有点复杂，我们前边说过，一个函数就是一个私有作用域，根据定义，在 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">fn2</code> 作用域中打印 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">a</code>，首先在自己所在作用域搜索，如果没有就向上级作用域搜索，直到搜索到全局作用域，<code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">a = 1</code>，找到了打印出值。整个搜索的过程，就是基于作用域链搜索的。</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E9%97%AD%E5%8C%85/%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%93%BE.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E9%97%AD%E5%8C%85/%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%93%BE.png"></p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是闭包？闭包的作用？闭包的应用？</p>
</blockquote>

<p>很多应聘者喜欢这样回答，“函数里套一个函数”，但是面试官更喜欢下面的回答，因为可以继续为你挖坑。</p>
<p>函数执行，形成一个私有的作用域，保护里边的私有变量不受外界的干扰，除了<span style="color:#ff502c;font-weight:bold;padding:0 2px">保护</span>私有变量外，还可以<span style="color:#ff502c;font-weight:bold;padding:0 2px">保存</span>一些内容，这样的模式叫做<span style="color:#ff502c;font-weight:bold;padding:0 2px">闭包</span>。</p>
<p>闭包的作用有两个，<span style="color:#ff502c;font-weight:bold;padding:0 2px">保护和保存。</span></p>
<p><strong>保护的应用</strong></p>
<ul>
<li>团队开发时，每个开发者把自己的代码放在一个私有的作用域中，防止相互之间的变量命名冲突；把需要提供给别人的方法，通过 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">return</code> 或 <code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">window.xxx </code>的方式暴露在全局下。</li>
<li><code style="background-color: #fff5f5;color: #ff502c;font-size: .87em;padding: .065em .4em;">jQuery</code> 的源码中也是利用了这种保护机制。</li>
<li>封装私有变量。</li>
</ul>
<p><strong>保存的应用</strong></p>
<ul>
<li>选项卡闭包的解决方案。</li>
</ul>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：循环绑定事件引发的索引什么问题？怎么解决这种问题？</p>
</blockquote>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 事件绑定引发的索引问题</span></span><br><span class="line"><span class="keyword">var</span> btnBox = <span class="built_in">document</span>.getElementById(<span class="string">'btnBox'</span>),</span><br><span class="line">    inputs = btnBox.getElementsByTagName(<span class="string">'input'</span>)</span><br><span class="line"><span class="keyword">var</span> len = inputs.length;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span>; i &lt; <span class="number">1</span>en; i++)&#123;</span><br><span class="line">    inputs[i].onclick = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        alert(i)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>闭包剩余的部分，俺在之前的文章已经总结过，俺就不复制过来了，直接传送过去~ <a href="https://juejin.im/post/5dc6449ae51d452bd321252c#comment" target="_blank" rel="noopener">动画：什么是闭包？</a></p>
<h3 id="原型和原型链"><a href="#原型和原型链" class="headerlink" title="原型和原型链"></a>原型和原型链</h3><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是原型？什么是原型链？如何理解？</p>
</blockquote>

<p><strong>原型：</strong>每个 <code>JS</code> 对象都有 <code>__proto__</code> 属性，这个属性指向了原型。跟俺去看看，</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B1.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B1.png"></p>
<p>再来一个，</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B2.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B2.png"></p>
<p>我们可以看到，只要是对象类型，都会有这个<code>__proto__</code> 属性，这个属性指向的也是一个原型对象，原型对象也是对象呀，肯定也会存在一个 <code>__proto__</code> 属性。那么就形成了原型链，定义如下：</p>
<p><strong>原型链</strong>：原型链就是多个对象通过 <code>__proto__</code> 的方式连接了起来形成一条链。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>原型和原型链是怎么来的呢？如果理清原型链中的关系呢？</p>
</blockquote>

<p>对于原型和原型链的前世今生，由于篇幅过大，俺的传送门~ <a href="https://juejin.im/post/5db0fec4518825648c3a8770" target="_blank" rel="noopener">图解：告诉面试官什么是 JS 原型和原型链?</a></p>
<blockquote>
<p>PS：下面的看不懂，一定去看文章哦！</p>
</blockquote>
<p>再往深处看，他们之间存在复杂的关系，但是这些所谓的负责关系俺已经总结好了，小二上菜</p>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B%E5%9B%BE.png" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E5%8E%9F%E5%9E%8B%E5%9B%BE.png"></p>
<p>这张图看起来真复杂，但是通过下边总结的，再来分析这张图，试试看。</p>
<ul>
<li>所有的实例的 <code>_proto_</code>都指向该构造函数的原型对象（<code>prototype</code>）。</li>
<li>所有的函数（包括构造函数）是 <code>Function()</code> 的实例，所以所有函数的 <code>_proto_</code>的都指向 <code>Function()</code> 的原型对象。</li>
<li>所有的原型对象（包括 <code>Function</code> 的原型对象）都是 <code>Object</code> 的实例，所以 <code>_proto_</code>都指向 Object （构造函数）的原型对象。而 <code>Object</code> 构造函数的 <code>_proto_</code>  指向 <code>null</code>。</li>
<li><code>Function</code> 构造函数本身就是 <code>Function</code> 的实例，所以 <code>_proto_</code> 指向 <code>Function</code> 的原型对象。</li>
</ul>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：instanceOf 的原理是什么？</p>
</blockquote>

<p>之前留了一个小问题，总结了上述的原型和原型链之后，<code>instanceof</code>的原理很容易理解。</p>
<p><code>instanceof</code> 的原理是通过判断该对象的原型链中是否可以找到该构造类型的 <code>prototype</code> 类型。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Foo</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line"><span class="keyword">var</span> f1 = <span class="keyword">new</span> Foo();</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(f1 <span class="keyword">instanceof</span> Foo);<span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/instanceof.jpg" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/instanceof.jpg"></p>
<h3 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h3><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说一说 JS 中的继承方式有哪些？以及各个继承方式的优缺点。</p>
</blockquote>



<h4 id="经典继承（构造函数）"><a href="#经典继承（构造函数）" class="headerlink" title="经典继承（构造函数）"></a>经典继承（构造函数）</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">/ 详细解析</span><br><span class="line"><span class="comment">//1、当用调用 call 方法时，this 带边 son 。</span></span><br><span class="line"><span class="comment">//2、此时 Father 构造函数中的 this 指向 son。</span></span><br><span class="line"><span class="comment">//3、也就是说 son 有了 colors 的属性。</span></span><br><span class="line"><span class="comment">//4、每 new 一个 son ，都会产生不同的对象，每个对象的属性都是相互独立的。</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Father</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">	<span class="keyword">this</span>.colors = [<span class="string">"red"</span>,<span class="string">"blue"</span>,<span class="string">"green"</span>];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Son</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="comment">// this 是通过 new 操作内部的新对象 &#123;&#125; ，</span></span><br><span class="line">    <span class="comment">// 此时 Father 中的 this 就是为 Son 中的新对象&#123;&#125;</span></span><br><span class="line">    <span class="comment">// 新对象就有了新的属性，并返回得到 new 的新对象实例</span></span><br><span class="line">    <span class="comment">// 继承了Father,且向父类型传递参数</span></span><br><span class="line">	Father.call(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> s = <span class="keyword">new</span> Son();</span><br><span class="line"><span class="built_in">console</span>.log(s.color)</span><br></pre></td></tr></table></figure>

<p><strong>① 基本思想：</strong>在子类的构造函数的内部调用父类的构造函数。</p>
<p><strong>② 优点：</strong></p>
<ul>
<li>保证了原型链中引用类型的独立，不被所有实例共享。</li>
<li>子类创建的时候可以向父类进行传参。</li>
</ul>
<p><strong>③ 缺点:</strong></p>
<ul>
<li>继承的方法都在构造函数中定义，构造函数不能够复用了（因为构造函数中存在子类的特殊属性，所以构造函数中复用的属性不能复用了）。</li>
<li>父类中定义的方法对于子类型而言是不可见的（子类所有的属性都定义在父类的构造函数当中）。</li>
</ul>
<h4 id="组合继承"><a href="#组合继承" class="headerlink" title="组合继承"></a>组合继承</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Father</span>(<span class="params">name</span>)</span>&#123;</span><br><span class="line">	<span class="keyword">this</span>.name = name;</span><br><span class="line">	<span class="keyword">this</span>.colors = [<span class="string">"red"</span>,<span class="string">"blue"</span>,<span class="string">"green"</span>];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 方法定义在原型对象上（共享）</span></span><br><span class="line">Father.prototype.sayName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">	alert(<span class="keyword">this</span>.name);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Son</span>(<span class="params">name,age</span>)</span>&#123;</span><br><span class="line">    <span class="comment">// 子类继承父类的属性  </span></span><br><span class="line">	Father.call(<span class="keyword">this</span>,name);     <span class="comment">//继承实例属性，第一次调用 Father()</span></span><br><span class="line">    <span class="comment">// 每个实例都有自己的属性</span></span><br><span class="line">	<span class="keyword">this</span>.age = age;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 子类和父类共享的方法（实现了父类属性和方法的复用）                              </span></span><br><span class="line">Son.prototype = <span class="keyword">new</span> Father();   <span class="comment">//继承父类方法,第二次调用 Father()</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 子类实例对象共享的方法</span></span><br><span class="line">Son.prototype.sayAge = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">	alert(<span class="keyword">this</span>.age);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> instance1 = <span class="keyword">new</span> Son(<span class="string">"louis"</span>,<span class="number">5</span>);</span><br><span class="line">instance1.colors.push(<span class="string">"black"</span>);</span><br><span class="line"><span class="built_in">console</span>.log(instance1.colors);<span class="comment">//"red,blue,green,black"</span></span><br><span class="line">instance1.sayName();<span class="comment">//louis</span></span><br><span class="line">instance1.sayAge();<span class="comment">//5</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> instance1 = <span class="keyword">new</span> Son(<span class="string">"zhai"</span>,<span class="number">10</span>);</span><br><span class="line"><span class="built_in">console</span>.log(instance1.colors);<span class="comment">//"red,blue,green"</span></span><br><span class="line">instance1.sayName();<span class="comment">//zhai</span></span><br><span class="line">instance1.sayAge();<span class="comment">//10</span></span><br></pre></td></tr></table></figure>

<p><strong>① 基本思想：</strong></p>
<ul>
<li>使用<strong>原型链</strong>实现对<strong>「原型对象属性和方法」</strong>的继承。</li>
<li>通过借用<strong>构造函数</strong>来实现对<strong>「实例属性」</strong>的继承。</li>
</ul>
<p><strong>② 优点：</strong></p>
<ul>
<li>在原型对象上定义的方法实现了函数的复用。</li>
<li>每个实例都有属于自己的属性。</li>
</ul>
<p><strong>③ 缺点：</strong></p>
<ul>
<li>组合继承调用了两次父类的构造函数，造成了不必要的消耗。</li>
</ul>
<h4 id="原型继承"><a href="#原型继承" class="headerlink" title="原型继承"></a>原型继承</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">object</span>(<span class="params">o</span>)</span>&#123;</span><br><span class="line">	<span class="function"><span class="keyword">function</span> <span class="title">F</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line">	F.prototype = o;</span><br><span class="line">    <span class="comment">// 每次返回的 new 是不同的</span></span><br><span class="line">	<span class="keyword">return</span> <span class="keyword">new</span> F();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> person = &#123;</span><br><span class="line">	friends : [<span class="string">"Van"</span>,<span class="string">"Louis"</span>,<span class="string">"Nick"</span>]</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 实例 1</span></span><br><span class="line"><span class="keyword">var</span> anotherPerson = object(person);</span><br><span class="line">anotherPerson.friends.push(<span class="string">"Rob"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 实例 2</span></span><br><span class="line"><span class="keyword">var</span> yetAnotherPerson = object(person);</span><br><span class="line">yetAnotherPerson.friends.push(<span class="string">"Style"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 都添加至原型对象的属性(所共享)</span></span><br><span class="line">alert(person.friends); <span class="comment">// "Van,Louis,Nick,Rob,Style"</span></span><br></pre></td></tr></table></figure>

<p><strong>① 基本思想：</strong>创建临时性的构造函数（无任何属性），将传入的对象作为该构造函数的原型对象，然后返回这个新构造函数的实例。</p>
<p><strong>② 浅拷贝：</strong></p>
<blockquote>
<p><code>object</code> 所产生的对象是不相同的，但是原型对象都是 <code>person</code> 对象，所改变存在原型对象的属性所有生成的实例所共享，不仅被 <code>Person</code> 所拥有，而且被子类生成的实例所共享。</p>
</blockquote>
<p>③ <strong>object.create()：</strong>在 ECMAScript5 中,通过新增 <strong>object.create()</strong> 方法规范化了上面的原型式继承.。</p>
<ul>
<li>参数一：新对象的原型的对象。</li>
<li>参数二：先对象定义额外的属性（可选）。</li>
</ul>
<h4 id="寄生式继承"><a href="#寄生式继承" class="headerlink" title="寄生式继承"></a>寄生式继承</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createAnother</span>(<span class="params">original</span>)</span>&#123;</span><br><span class="line">	<span class="keyword">var</span> clone = object(original); <span class="comment">// 通过调用object函数创建一个新对象</span></span><br><span class="line">	clone.sayHi = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; <span class="comment">// 以某种方式来增强这个对象</span></span><br><span class="line">		alert(<span class="string">"hi"</span>);</span><br><span class="line">	&#125;;</span><br><span class="line">	<span class="keyword">return</span> clone; <span class="comment">//返回这个对象</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li><strong>基本思想</strong>：不必为了指定子类型的原型而调用超类型的构造函数（避免第二次调用的构造函数）。</li>
<li><strong>优点</strong>：寄生组合式继承就是为了解决组合继承中两次调用构造函数的开销。</li>
</ul>
<h3 id="垃圾回收机制"><a href="#垃圾回收机制" class="headerlink" title="垃圾回收机制"></a>垃圾回收机制</h3><p>说到 <code>Javascript</code>的垃圾回收机制，我们要从内存泄漏一步步说起。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是内存泄漏？为什么会导致内存泄漏？</p>
</blockquote>

<p><span style="color:#ff502c;font-weight:bold;padding:0 2px">不再用到的内存，没有及时释放，就叫做内存泄漏。</span></p>
<p><strong>内存泄漏是指我们已经无法再通过js代码来引用到某个对象，但垃圾回收器却认为这个对象还在被引用，因此在回收的时候不会释放它</strong>。导致了分配的这块内存永远也无法被释放出来。如果这样的情况越来越多，会导致内存不够用而系统崩溃。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：怎么解决内存泄漏？说一说 JS 垃圾回收机制的运行机制的原理？。</p>
</blockquote>

<p>很多编程语言需要手动释放内存，但是很多开发者喜欢系统提供自动内存管理，减轻程序员的负担，这被称为<span style="color:#ff502c;font-weight:bold;padding:0 2px">“垃圾回收机制”</span>。</p>
<p>之所以会有垃圾回收机制，是因为 <code>js</code> 中的字符串、对象、数组等只有确定固定大小时，才会动态分配内存，只要像这样动态地分配了内存，最终都要释放这些内存以便他们能够被再用，否则，<code>JavaScript</code> 的解释器将会消耗完系统中所有可用的内存，造成系统崩溃</p>
<p><code>JavaScript</code>与其他语言不同，它具有自动垃圾收集机制，执行环境会负责管理代码执行过程中使用的内存。</p>
<h4 id="两种垃圾回收策略"><a href="#两种垃圾回收策略" class="headerlink" title="两种垃圾回收策略"></a>两种垃圾回收策略</h4><p>找出那些不再继续使用的变量，然后释放其内存。垃圾回收器会按照固定的时间间隔，周期性的执行该垃圾回收操作。</p>
<p>共有两种策略：</p>
<ul>
<li><strong>标记清除法</strong></li>
<li><strong>引用计数法</strong></li>
</ul>
<h4 id="标记清除法"><a href="#标记清除法" class="headerlink" title="标记清除法"></a>标记清除法</h4><p>垃圾回收器会在运行的时候，会给存储在内存中的所有变量都加上标记，然后它会去掉环境中变量以及被环境中的变量引用的变量的标记。剩下的就视为即将要删除的变量，原因是在环境中无法访问到这些变量了。最后垃圾回收器完成内存清除操作。</p>
<p><span style="color:#ff502c;font-weight:bold;padding:0 2px">它的实现原理就是通过判断一个变量是否在执行环境中被引用，来进行标记删除。</span></p>
<h4 id="引用计数法"><a href="#引用计数法" class="headerlink" title="引用计数法"></a>引用计数法</h4><p>引用计数的垃圾收集策略不常用，引用计数的最基本含义就是跟踪记录每个值被引用的次数。</p>
<p>当声明变量并将一个引用类型的值赋值给该变量时，则这个值的引用次数加 1，同一值被赋予另一个变量，该值的引用计数加 1 。当引用该值的变量被另一个值所取代，则引用计数减 1，当计数为 0 的时候，说明无法在访问这个值了，所有系统将会收回该值所占用的内存空间。</p>
<p><span style="color:#ff502c;font-weight:bold;padding:0 2px">存在的缺陷：</span></p>
<p>两个对象的相互循环引用，在函数执行完成的时候，两个对象相互的引用计数并未归 0 ，而是依然占据内存，无法回收，当该函数执行多次时，内存占用就会变多，导致大量的内存得不到回收。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>最常见的就是在 IE BOM 和 DOM 中，使用的对象并不是 js 对象，所以垃圾回收是基于计数策略的。但是在 IE9 已经将 BOM 和 DOM 真正的转化为了 js 对象，所以循环引用的问题得到解决。</p>
</blockquote>



<h4 id="如何管理内存"><a href="#如何管理内存" class="headerlink" title="如何管理内存"></a>如何管理内存</h4><p>虽然说是 <code>js</code> 的内存都是自动管理的，但是对于 <code>js</code>  还是存在一些问题的，最主要的一个问题就是<strong>分配给 Web 浏览器的可用内存数量通常比分配给桌面应用程序的少</strong>。</p>
<blockquote>
<p>为了能够让页面获得最好的性能，必须确保 js 变量占用最少的内存，最好的方式就是将不用的变量引用释放掉，也叫做<strong>解除引用</strong>。</p>
</blockquote>
<ul>
<li>对于局部变量来说，函数执行完成离开环境变量，变量将自动解除。</li>
<li>对于全局变量我们需要进行手动解除。（注意：解除引用并不意味被收回，而是将变量真正的脱离执行环境，下一次垃圾回收将其收回）</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">20</span>;  <span class="comment">// 在堆内存中给数值变量分配空间</span></span><br><span class="line">alert(a + <span class="number">100</span>);  <span class="comment">// 使用内存</span></span><br><span class="line"><span class="keyword">var</span> a = <span class="literal">null</span>; <span class="comment">// 使用完毕之后，释放内存空间</span></span><br></pre></td></tr></table></figure>

<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>补充：因为通过上边的垃圾回收机制的标记清除法的原理得知，只有与环境变量失去引用的变量才会被标记回收，所用上述例子通过将对象的引用设置为 null ，此变量也就失去了引用，等待被垃圾回收器回收。</p>
</blockquote>



<h3 id="深拷贝和浅拷贝"><a href="#深拷贝和浅拷贝" class="headerlink" title="深拷贝和浅拷贝"></a>深拷贝和浅拷贝</h3><blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是深拷贝？什么是浅拷贝？</p>
</blockquote>

<p>上边在 <code>JavaScript</code> 基本类型中我们说到，数据类型分为<strong>基本类型和引用类型</strong>。对基本类型的拷贝就是对值复制进行一次拷贝，而对于引用类型来说，拷贝的不是值，而是<strong>值的地址</strong>，最终两个变量的地址指向的是同一个值。还是以前的例子：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">var</span> b = a;</span><br><span class="line">b = <span class="number">30</span>;</span><br><span class="line"><span class="built_in">console</span>.log(a); <span class="comment">// 10值</span></span><br><span class="line"><span class="built_in">console</span>.log(b); <span class="comment">// 30值</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> obj1 = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line"><span class="keyword">var</span> obj2 = obj1;</span><br><span class="line">obj2.name = <span class="string">"小鹿"</span>;</span><br><span class="line"><span class="built_in">console</span>.log(obj1.name); <span class="comment">// 小鹿</span></span><br></pre></td></tr></table></figure>



<p>要想将 <code>obj1</code> 和 <code>obj2</code> 的关系断开，也就是不让他指向同一个地址。根据不同层次的拷贝，分为深拷贝和浅拷贝。</p>
<ul>
<li><strong>浅拷贝：</strong>只进行一层关系的拷贝。</li>
<li><strong>深拷贝：</strong>进行无限层次的拷贝。</li>
</ul>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：浅拷贝和深拷贝分别如何实现的？有哪几种实现方式？</p>
</blockquote>

<ul>
<li>自己实现一个浅拷贝：</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 实现浅克隆</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">shallowClone</span>(<span class="params">o</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> obj = &#123;&#125;;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">let</span> i <span class="keyword">in</span> o)&#123;</span><br><span class="line">        obj[i] = o[i]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> obj;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>扩展运算符实现：</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = &#123;<span class="attr">c</span>: <span class="number">1</span>&#125;</span><br><span class="line"><span class="keyword">let</span> b = &#123;...a&#125;</span><br><span class="line">a.c = <span class="number">2</span></span><br><span class="line"><span class="built_in">console</span>.log(b.c) <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<ul>
<li><code>Object.assign()</code>实现</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = &#123;<span class="attr">c</span>: <span class="number">1</span>&#125;</span><br><span class="line"><span class="keyword">let</span> b = <span class="built_in">Object</span>.assign(&#123;&#125;, a)</span><br><span class="line">a.c = <span class="number">2</span></span><br><span class="line"><span class="built_in">console</span>.log(b.c) <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>



<p>对于深拷贝来说，在浅拷贝的基础上加上递归，我们改动上边自己实现的浅拷贝代码：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a1 = &#123;<span class="attr">b</span>: &#123;<span class="attr">c</span>: &#123;<span class="attr">d</span>: <span class="number">1</span>&#125;&#125;;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">clone</span>(<span class="params">source</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> target = &#123;&#125;;</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">var</span> i <span class="keyword">in</span> source) &#123;</span><br><span class="line">        <span class="keyword">if</span> (source.hasOwnProperty(i)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">typeof</span> source[i] === <span class="string">'object'</span>) &#123;</span><br><span class="line">                target[i] = clone(source[i]); <span class="comment">// 递归</span></span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                target[i] = source[i];</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> target;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>如果功底稍微扎实的小伙伴可以看出上边深拷贝存在的问题：</p>
<ul>
<li>参数没有做检验;</li>
<li>判断对象不够严谨;</li>
<li>没有考虑到数组，以及 <code>ES6</code> 的 <code>set, map, weakset, weakmap</code>兼容性。</li>
<li>最严重的问题就是递归容易爆栈（递归层次很深的时候）。</li>
<li>循环引用问题提。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123;&#125;;</span><br><span class="line">a.a = a;</span><br><span class="line">clone(a); <span class="comment">// 会造成一个死循环</span></span><br></pre></td></tr></table></figure>

<p>两种解决循环引用问题的办法：</p>
<ul>
<li><strong>暴力破解</strong></li>
<li><strong>循环检测</strong></li>
</ul>
<p>还有一个最简单的实现深拷贝的方式，那就是利用 <code>JSON.parse(JSON.stringify(object))</code>,但是也存在一定的局限性。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">cloneJSON</span>(<span class="params">source</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(source));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>对于这种方法来说，内部的原理实现也是使用的递归，递归到一定深度，也会出现爆栈问题。但是对于循环引用的问题不会出现，内部的解决方案正是用到了循环检测。对于详细的实现一个深拷贝，具体参考文章：<a href="https://segmentfault.com/a/1190000016672263" target="_blank" rel="noopener"><a href="https://segmentfault.com/a/1190000016672263" target="_blank" rel="noopener">深拷贝的终极探索</a></a></p>
<h3 id="异步编程"><a href="#异步编程" class="headerlink" title="异步编程"></a>异步编程</h3><p>由于 <code>JavaScript</code> 是单线程的，单线程就意味着阻塞问题，当一个任务执行完成之后才能执行下一个任务。这样就会导致出现页面卡死的状态，页面无响应，影响用户的体验，所以不得不出现了同步和异步的解决方案。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：JS 为什么是单线程？又带来了哪些问题呢？</p>
</blockquote>

<p>JS 单线程的特点就是同一时刻只能执行一个任。这是由一些与用户的互动以及操作 <code>DOM</code> 等相关的操作决定了 JS 要使用单线程，否则使用多线程会带来复杂的同步问题。如果执行同步问题的话，多线程需要加锁，执行任务造成非常的繁琐。</p>
<p>虽然 HTML5 标准规定，允许 <code>JavaScript</code> 脚本创建多个线程，但是子线程完全受主线程控制，且不得操作 <code>DOM</code>。</p>
<p>上述开头我们也说到了，单线程带来的问题就是会导致阻塞问题，为了解决这个问题，就不得不涉及 JS 的两种任务，分别为同步任务和异步任务。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：JS 如何实现异步编程？</p>
</blockquote>

<p>最早的解决方案是使用回调函数，回调函数不是直接调用，而是在特定的事件或条件发生时另一方调用的，用于对该事件或条件进行响应。比如 Ajax 回调： </p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// jQuery 中的 ajax</span></span><br><span class="line">$.ajax(&#123; </span><br><span class="line">    type : <span class="string">"post"</span>, </span><br><span class="line">    url : <span class="string">'test.json'</span>, </span><br><span class="line">    dataType : <span class="string">'json'</span>, </span><br><span class="line">    success : <span class="function"><span class="keyword">function</span>(<span class="params">res</span>) </span>&#123; </span><br><span class="line">       <span class="comment">// 响应成功回调</span></span><br><span class="line">    &#125;,</span><br><span class="line">    fail: <span class="function"><span class="keyword">function</span>(<span class="params">err</span>)</span>&#123;</span><br><span class="line">       <span class="comment">// 响应失败回调</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>但是如果某个请求存在依赖性，如下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">$.ajax(&#123;</span><br><span class="line">    type:<span class="string">"post"</span>,</span><br><span class="line">    success: <span class="function"><span class="keyword">function</span>(<span class="params">res</span>)</span>&#123;<span class="comment">//成功回调</span></span><br><span class="line">        <span class="comment">//再次异步请求</span></span><br><span class="line">        $.ajax(&#123;</span><br><span class="line">            type:<span class="string">"post"</span>,</span><br><span class="line">            url:<span class="string">"...?id=res.id,</span></span><br><span class="line"><span class="string">            success:function(res)&#123;</span></span><br><span class="line"><span class="string">                 $.ajax(&#123;</span></span><br><span class="line"><span class="string">                    type:"</span>post<span class="string">",</span></span><br><span class="line"><span class="string">                    url:"</span>...?id=res.id,</span><br><span class="line">                    success:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">						<span class="comment">// 往复循环</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>就会形成不断的循环嵌套，我们称之为回调地狱。我们可以看出回调地狱有以下缺点：</p>
<ul>
<li>嵌套函数存在耦合性，一旦有所改动，牵一发而动全身。</li>
<li>嵌套函数一多，就很难处理错误。</li>
<li>回调函数不能使用 <code>try catch</code> 捕获异常(异常的捕获只能在函数执行的时候才能捕获到)。</li>
<li>回调函数不能直接 <code>return</code>。</li>
</ul>
<p>以上有两个地方俺需要再进一步详细说明一下：</p>
<ul>
<li><strong>为什么不能捕获异常？</strong></li>
</ul>
<p>其实这跟 <code>js</code> 的运行机制相关，异步任务执行完成会加入任务队列，当执行栈中没有可执行任务了，主线程取出任务队列中的异步任务并入栈执行，当异步任务执行的时候，捕获异常的函数已经在执行栈内退出了，所以异常无法被捕获。</p>
<ul>
<li><strong>为什么不能return？</strong></li>
</ul>
<p><code>return</code> 只能终止回调的函数的执行，而不能终止外部代码的执行。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：如何解决回调地狱问题呢？</p>
</blockquote>

<p>既然回调函数存在回调地狱问题，那我们如何解决呢？ES6 给我们提供了三种解决方案，分别是 Generator、Promise、async/await（ES7）。</p>
<p>由于这部分涉及到 ES6 部分的知识，这一期是有关 JS 的，所以会在下一期进行延伸，这里不多涉及。</p>
<p>【留下一个传送门~】</p>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说异步代码的执行顺序？Event Loop 的运行机制是如何的运行的？</p>
</blockquote>

<p>上边我们说到 <code>JS</code>  是单线程且使用同步和异步任务解决 <code>JS</code> 的阻塞问题，那么异步代码的执行顺序以及 <code>EventLoop</code> 是如何运作的呢？</p>
<p>在深入事件循环机制之前，需要弄懂一下几个概念：</p>
<ul>
<li><span style="color:#ff502c;font-weight:bold;padding:0 2px">执行上下文</span>(<code>Execution context</code>)</li>
<li><span style="color:#ff502c;font-weight:bold;padding:0 2px">执行栈</span>（<code>Execution stack</code>）</li>
<li><span style="color:#ff502c;font-weight:bold;padding:0 2px">微任务</span>（<code>micro-task</code>）</li>
<li><span style="color:#ff502c;font-weight:bold;padding:0 2px">宏任务</span>（<code>macro-task</code>）</li>
</ul>
<h4 id="执行上下文"><a href="#执行上下文" class="headerlink" title="执行上下文"></a>执行上下文</h4><p>执行上下文是一个抽象的概念，可以理解为是代码执行的一个环境。JS 的执行上下文分为三种，<span style="color:#ff502c;font-weight:bold;padding:0 2px">全局执行上下文、函数(局部)执行上下文、Eval 执行上下文</span>。</p>
<ul>
<li><strong>全局执行上下文：</strong>全局执行上下文指的是全局 <code>this</code> 指向的 <code>window</code>，可以是外部加载的 JS 文件或者本地<code>&lt;scripe&gt;&lt;/script&gt;</code>标签中的代码。</li>
<li><strong>函数执行上下文：</strong>函数上下文也称为局部上下文，每个函数被调用的时候，都会创建一个新的局部上下文。</li>
<li><strong>Eval 执行上下文：</strong> 这个不经常用，所以不多讨论。</li>
</ul>
<h4 id="执行栈"><a href="#执行栈" class="headerlink" title="执行栈"></a>执行栈</h4><p>执行栈，就是我们数据结构中的“栈”，它具有“先进后出”的特点，正是因为这种特点，在我们代码进行执行的时候，遇到一个执行上下文就将其依次压入执行栈中。</p>
<p>当代码执行的时候，先执行位于栈顶的执行上下文中的代码，当栈顶的执行上下文代码执行完毕就会出栈，继续执行下一个位于栈顶的执行上下文。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'a'</span>);</span><br><span class="line">  bar();</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'b'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'c'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">foo();</span><br></pre></td></tr></table></figure>

<ul>
<li>初始化状态，执行栈任务为空。</li>
<li><code>foo</code> 函数执行，<code>foo</code> 进入执行栈，输出 <code>a</code>，碰到函数<code>bar</code>。</li>
<li>然后 bar 再进入执行栈，开始执行 <code>bar</code> 函数，输出 <code>c</code>。</li>
<li><code>bar</code> 函数执行完出栈，继续执行执行栈顶端的函数 <code>foo</code>，最后输出 <code>c</code>。</li>
<li><code>foo</code> 出栈，所有执行栈内任务执行完毕。</li>
</ul>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E6%89%A7%E8%A1%8C%E6%A0%88.gif" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E5%8E%9F%E5%9E%8B/%E6%89%A7%E8%A1%8C%E6%A0%88.gif"></p>
<h4 id="宏任务"><a href="#宏任务" class="headerlink" title="宏任务"></a>宏任务</h4><p>对于宏任务一般包括：</p>
<ul>
<li>整体的 <code>script</code> 标签内的代码，</li>
<li><code>setTimeout</code></li>
<li><code>setInterval</code></li>
<li><code>setImmediate</code></li>
<li><code>I/O</code></li>
</ul>
<h4 id="微任务"><a href="#微任务" class="headerlink" title="微任务"></a>微任务</h4><p>对于微任务一般包括：</p>
<ul>
<li><code>Promise</code></li>
<li><code>process.nextTick</code>(Node)</li>
<li><code>MutationObserver</code></li>
</ul>
<blockquote>
<p>注意：nextTick 队列会比 Promie 队列先执行。</p>
</blockquote>
<p>以上概念弄明白之后，再来看循环机制是如何运行的呢？以下涉及到的任务执行顺序都是靠函数调用栈来实现的。</p>
<p>1）首先，事件循环机制的是从 <code>&lt;script&gt;</code> 标签内的代码开始的，上边我们提到过，整个 script 标签作为一个宏任务处理的。</p>
<p>2）在代码执行的过程中，如果遇到宏任务，如：<code>setTimeout</code>，就会将当前任务分发到对应的执行队列中去。</p>
<p>3）当执行过程中，如果遇到微任务，如：<code>Pomise</code>，在创建 <code>Promise</code>实例对象时,代码顺序执行，如果到了执行· <code>then</code> 操作，该任务就会被分发到微任务队列中去。</p>
<p>4）<code>script</code> 标签内的代码执行完毕，同时执行过程中所涉及到的宏任务也和微任务也分配到相应的队列中去。</p>
<p>5）此时宏任务执行完毕，然后去微任务队列执行所有的存在的微任务。</p>
<p>6）微任务执行完毕，第一轮的消息循环执行完毕，页面进行一次渲染。</p>
<p>7）然后开始第二轮的消息循环，从宏任务队列中取出任务执行。</p>
<p>8）如果两个任务队列没有任务可执行了，此时所有任务执行完毕。</p>
<p><strong>实战一下：</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html lang=<span class="string">"en"</span>&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">    &lt;meta charset=<span class="string">"UTF-8"</span>&gt;</span><br><span class="line">    &lt;meta name=<span class="string">"viewport"</span> content=<span class="string">"width=device-width, initial-scale=1.0"</span>&gt;</span><br><span class="line">    &lt;meta http-equiv=<span class="string">"X-UA-Compatible"</span> content=<span class="string">"ie=edge"</span>&gt;</span><br><span class="line">    &lt;title&gt;消息运行机制&lt;<span class="regexp">/title&gt;</span></span><br><span class="line"><span class="regexp">&lt;/</span>head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line"></span><br><span class="line">&lt;<span class="regexp">/body&gt;</span></span><br><span class="line"><span class="regexp">    &lt;script&gt;</span></span><br><span class="line"><span class="regexp">        console.log('1');</span></span><br><span class="line"><span class="regexp">        setTimeout(() =&gt; &#123;</span></span><br><span class="line"><span class="regexp">            console.log('2')</span></span><br><span class="line"><span class="regexp">        &#125;, 1000);</span></span><br><span class="line"><span class="regexp">        new Promise((resolve, reject) =&gt; &#123;</span></span><br><span class="line"><span class="regexp">            console.log('3');</span></span><br><span class="line"><span class="regexp">            resolve();</span></span><br><span class="line"><span class="regexp">            console.log('4');</span></span><br><span class="line"><span class="regexp">        &#125;).then(() =&gt; &#123;</span></span><br><span class="line"><span class="regexp">            console.log('5');</span></span><br><span class="line"><span class="regexp">        &#125;);</span></span><br><span class="line"><span class="regexp">        console.log('6');/</span><span class="regexp">/ 1,3,4,6,5,2</span></span><br><span class="line"><span class="regexp">    &lt;/</span>script&gt;</span><br><span class="line">&lt;<span class="regexp">/html&gt;</span></span><br></pre></td></tr></table></figure>

<ul>
<li>初始化状态，执行栈为空。</li>
<li>首先执行 <code>&lt;script&gt;</code> 标签内的同步代码，此时全局的代码进入执行栈中，同步顺序执行代码，输出 1。</li>
<li>执行过程中遇到异步代码 <code>setTimeout</code>（宏任务），将其分配到宏任务异步队列中。</li>
<li>同步代码继续执行，遇到一个 <code>promise</code> 异步代码（微任务）。但是构造函数中的代码为同步代码，依次输出3、4，则 then 之后的任务加入到微任务队列中去。</li>
<li>最后执行同步代码，输出 6。</li>
<li>因为 <code>script</code>内的代码作为宏任务处理，所以此次循环进行到处理微任务队列中的所有异步任务，直达微任务队列中的所有任务执行完成为止，微任务队列中只有一个微任务，所以输出 5。</li>
<li>此时页面要进行一次页面渲染，渲染完成之后，进行下一次循环。</li>
<li>在宏任务队列中取出一个宏任务，也就是之前的 <code>setTimeout</code>，最后输出 2。</li>
<li>此时任务队列为空，执行栈中为空，整个程序执行完毕。</li>
</ul>
<p><img src="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%B6%88%E6%81%AF%E5%BE%AA%E7%8E%AF/%E6%B6%88%E6%81%AF%E5%BE%AA%E7%8E%AF.gif" alt="https://github.com/luxiangqiang/Web-interview/blob/master/images/%E6%B6%88%E6%81%AF%E5%BE%AA%E7%8E%AF/%E6%B6%88%E6%81%AF%E5%BE%AA%E7%8E%AF.gif"></p>
<p>以上难免有些啰嗦，所以简化整理如下步骤：</p>
<ul>
<li>一开始执行宏任务（<code>script</code>中同步代码），执行完毕，调用栈为空。</li>
<li>然后检查微任务队列是否有可执行任务，执行完所有微任务。</li>
<li>进行页面渲染。</li>
<li>第二轮从宏任务队列取出一个宏任务执行，重复以上循环。</li>
</ul>
<h2 id="ES6-基础知识点"><a href="#ES6-基础知识点" class="headerlink" title="ES6 基础知识点"></a>ES6 基础知识点</h2><h3 id="变量提升"><a href="#变量提升" class="headerlink" title="变量提升"></a>变量提升</h3> <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是变量提升？为什么存在变量提升？</p>
</blockquote>

<p>变量提升就是该变量还未被声明，但是却可以使用未声明的变量。</p>
<p>虽然描述为提升，但不是真正的将代码提升到顶部，而是在代码执行前，先在词法环境中进行了注册。</p>
<p>如果没有变量提升，下方代码就无法执行：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn1</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    fn2();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn2</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    fn1();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">fn1();</span><br></pre></td></tr></table></figure>

<p>变量提升的根本原因就是为了解决函数之间互相调用的情况。</p>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：变量和函数怎么进行提升的？优先级是怎么样的？</p>
</blockquote>

<ul>
<li><p><strong>第一阶段：</strong>对所有<strong>函数声明</strong>进行提升（<strong>忽略表达式和箭头函数</strong>），引用类型的赋值（函数的声明，函数的提升代表着可执行，因为提升之后保持着引用）分为三步：</p>
<ul>
<li>开辟堆空间</li>
<li>存储内容</li>
<li>将地址赋值给变量</li>
</ul>
</li>
<li><p><strong>第二阶段：</strong>对所<strong>有的变量</strong>进行提升，全部赋值为 <code>undefined</code>（如果已经存在，不赋值为<code>undefined</code>）。然后依次顺序执行代码。</p>
<blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
  <p>PS：使用 let 和 const 时，我们不能在声明之前使用变量，这叫做暂时性死区。</p>
</blockquote>



</li>
</ul>
<h3 id="var、let、const"><a href="#var、let、const" class="headerlink" title="var、let、const"></a>var、let、const</h3> <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：var、let、const 三者的区别什么？</p>
</blockquote>

<ul>
<li><code>var</code> 存在变量提升，而 <code>let、const</code> 则不会。</li>
<li><code>var</code> 声明的变量会挂载到 <code>window</code> 上，而其他两者不会。</li>
<li><code>let</code> 和 <code>const</code> 的作用基本一致，后者声明的变量不能再次赋值（注意：但是能改变值）</li>
</ul>
<h3 id="map、filter、reduce"><a href="#map、filter、reduce" class="headerlink" title="map、filter、reduce"></a>map、filter、reduce</h3><p>这三个的区别经常出现于面试中，同时在实际项目中也是会频繁的使用，从如何使用到什么业务逻辑下使用是非常重要滴~</p>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 map、filter、reduce三者的使用以及区别是什么？</p>
</blockquote>

<h4 id="map"><a href="#map" class="headerlink" title="map"></a>map</h4><p><code>map</code> 的作用是 <code>map</code> 中传入一个函数，该函数会遍历该数组，对每一个元素做变换之后返回新数组。</p>
<ul>
<li><code>element :</code>  对应数组的每个元素。</li>
<li><code>index</code>: 数组元素的下标。</li>
<li><code>arr :</code> 原数组。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]</span><br><span class="line">arr = arr.map(<span class="function"><span class="keyword">function</span>(<span class="params">element,index,arr</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> arr[index]+<span class="number">1</span>;</span><br><span class="line">&#125;) <span class="comment">// [3,4,5]</span></span><br></pre></td></tr></table></figure>

<h4 id="filter"><a href="#filter" class="headerlink" title="filter"></a>filter</h4><p><code>filter</code> 的作用是也是生成一个数组，传入的函数返回值确实布尔类型，返回值为 <code>true</code> 的元素放入新数组，通常来筛选删除不需要的元素。</p>
<ul>
<li><code>element :</code>  对应数组的每个元素。</li>
<li><code>index :</code> 数组元素的下标。</li>
<li><code>arr :</code> 原数组。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> array = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>]</span><br><span class="line"><span class="keyword">let</span> arr = array.filter(<span class="function"><span class="keyword">function</span>(<span class="params">element</span>)</span>&#123;</span><br><span class="line">	<span class="keyword">return</span> element != <span class="number">6</span>;</span><br><span class="line">&#125;)<span class="comment">// [1,2,4]</span></span><br></pre></td></tr></table></figure>

<h4 id="reduce"><a href="#reduce" class="headerlink" title="reduce"></a>reduce</h4><p><code>reduce</code> 可以将数组中的元素通过回调函数最终转换为一个值。    </p>
<ul>
<li><code>acc：</code>累计值(第一次的值代表初始化的值)。</li>
<li><code>element：</code> 当前元素。</li>
<li><code>index：</code> 当前索引。</li>
<li><code>arr：</code> 原数组。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]</span><br><span class="line"><span class="keyword">let</span> sum = arr.reduce(<span class="function"><span class="keyword">function</span>(<span class="params">acc,element</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> acc + element;</span><br><span class="line">&#125;,<span class="number">0</span>) <span class="comment">// 6</span></span><br></pre></td></tr></table></figure>



<h3 id="Proxy"><a href="#Proxy" class="headerlink" title="Proxy"></a>Proxy</h3><p>对于 <code>Proxy</code> 代理我们从最基本的 <code>getter</code> 和 <code>setter</code> 说起~</p>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：通过 getter 与 setter 访问属性值有什么好处？代理与 getter 和 setter 的主要区别是什么？</blockquote>

<p>我们为什么会使用 <code>getter</code> 和 <code>setter</code> 来进行控制对值的访问呢，有以下是三个作用：</p>
<ul>
<li>避免意外的错误发生。</li>
<li>需要记录属性的变化：比如属性值的访问日志记录。</li>
<li>数据绑定：在 <code>vue</code> 中使用的数据的双向绑定。</li>
</ul>
<p>对于有哪几种方式来定义 <code>getter</code> 和 <code>setter</code> 呢？</p>
<ul>
<li>字面量定义;</li>
<li><code>ES6</code> 中的 <code>Class</code> 定义;</li>
<li>使用 <code>Object.definedProperty</code> 方法;</li>
</ul>
<h4 id="字面量定义"><a href="#字面量定义" class="headerlink" title="字面量定义"></a>字面量定义</h4><p>对象访问属性通常隐式调用 <code>getter</code> 和 <code>setter</code> 方法，属性自动关联 <code>getter</code> 和 <code>setter</code> 方法。这些都是标准方法，在访问属性的时候都是立即执行的。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> collection = &#123;</span><br><span class="line">	name=<span class="string">'xiaolu'</span>,</span><br><span class="line">	</span><br><span class="line">	<span class="comment">// 读取属性</span></span><br><span class="line">	<span class="keyword">get</span> name()&#123;</span><br><span class="line">		<span class="keyword">return</span> <span class="keyword">this</span>.name;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="comment">// 设置属性</span></span><br><span class="line">	<span class="keyword">set</span> name(value)&#123;</span><br><span class="line">		<span class="keyword">this</span>.name = value;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line">collection.name 			<span class="comment">// 隐士调用 getter 方法</span></span><br><span class="line">collection.name = <span class="string">"xiaolu1"</span> <span class="comment">// 隐士调用 setter 方法</span></span><br></pre></td></tr></table></figure>



<h4 id="ES6-中的-Class-定义"><a href="#ES6-中的-Class-定义" class="headerlink" title="ES6 中的 Class 定义"></a>ES6 中的 Class 定义</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// calss 定义 setter 和 getter</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Xiaolu</span> </span>&#123;</span><br><span class="line">    <span class="keyword">constructor</span>()&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = <span class="string">'xiaolu'</span></span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="keyword">get</span> firstXiaolu()&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'属性已访问'</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.name;</span><br><span class="line">    &#125;</span><br><span class="line">	</span><br><span class="line">    <span class="keyword">set</span> firstXiaolu(value)&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = value;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> x = <span class="keyword">new</span> Xiaolu();</span><br><span class="line">x.firstXiaolu</span><br></pre></td></tr></table></figure>



<h4 id="Object-definedProperty"><a href="#Object-definedProperty" class="headerlink" title="Object.definedProperty()"></a>Object.definedProperty()</h4><p>对象的字面量与类、<code>getter</code> 和 <code>setter</code> 方法不是在一同一作用域定义的，因此那些希望作为私有变量属性的标量是无法实现的。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Object.definedProperty</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">xiaolu</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> count = <span class="number">0</span>;</span><br><span class="line">	</span><br><span class="line">    <span class="built_in">Object</span>.defineProperty(<span class="keyword">this</span>,<span class="string">'skillLevel'</span>,&#123;</span><br><span class="line">        <span class="keyword">get</span>:() =&gt; &#123;</span><br><span class="line">            <span class="keyword">return</span> count;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="keyword">set</span>:value =&gt; &#123;</span><br><span class="line">            count = value;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 隐士的调用 get 方法</span></span><br><span class="line"><span class="built_in">console</span>.log(xiaolu.count)</span><br></pre></td></tr></table></figure>

<p>通过 <code>Object.definedProperty()</code> 创建的 <code>get</code> 和 <code>set</code> 方法，与私有的变量处于相同的作用域中，<code>get</code>和 <code>set</code>方法分别创建了含有私有变量的闭包。</p>
<h4 id="Proxy-代理"><a href="#Proxy-代理" class="headerlink" title="Proxy 代理"></a>Proxy 代理</h4> <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 ES6 中的 Proxy 和 getter、setter 的区别？</blockquote>

<p>代理 <code>proxy</code> 是 <code>ES6</code> 新提出的。代理（<code>proxy</code>）使我们通过代理控制对另一个对象的访问。<code>proxy</code> 和 <code>getter</code> 以及 <code>setter</code> 的区别是，<code>getter</code>和 <code>setter</code> 仅仅控制的是单个对象属性，而 <code>proxy</code> 代理的是对象交互的通用处理，包括对象的方法。</p>
<p><strong>用法：</strong></p>
<ul>
<li><strong><code>target</code>：</strong>要进行代理的对象。</li>
<li><strong><code>handler</code>：</strong>是一个特定的对象，定义了特定行为时触发的函数。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(target, handler);</span><br></pre></td></tr></table></figure>

<p><strong><code>get</code> 和 <code>set</code> 的参数：</strong></p>
<ul>
<li><code>target:</code> 传入的对象。</li>
<li><code>key:</code> 属性。</li>
<li><code>value:</code> 要赋的值。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> obj = &#123;<span class="attr">name</span>:<span class="string">'xiaolu'</span>&#125;</span><br><span class="line"><span class="keyword">const</span> representtive = <span class="keyword">new</span> <span class="built_in">Proxy</span>(obj, &#123;</span><br><span class="line">    <span class="keyword">get</span>: (target, key) =&gt;&#123;</span><br><span class="line">        <span class="keyword">return</span> key <span class="keyword">in</span> target ? target[key]:<span class="string">"不存在该值“</span></span><br><span class="line"><span class="string">    &#125;,</span></span><br><span class="line"><span class="string">    set: (target, key, value)=&gt;&#123;</span></span><br><span class="line"><span class="string">        target[key] = value;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">&#125;)</span></span><br></pre></td></tr></table></figure>

<p>我们试图想使用代理访问对象时，此时会触发 <code>get</code> 方法。或者试图将代理的对象进行赋值时，会触发调用 <code>set</code>方法。</p>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 Proxy 的基本应用？</blockquote>

<p>最基本的应用如下一个：</p>
<ul>
<li>日志记录 —— 当访问属性时，可以在 <code>get</code> 和 `set 中记录访问日志。</li>
<li>校验值 —— 有效的避免指定属性类型错误的发生。</li>
<li>定义如何计算属性值 —— 每次访问属性值，都会进行计算属性值。</li>
<li>数据的双向绑定（<code>Vue</code>）—— 在 <code>Vue3.0</code> 中将会通过 <code>Proxy</code> 来替换原本的 <code>Object.defineProperty</code> 来实现数据响应式。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 校验值</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">xiaolu</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> count = <span class="number">0</span>;</span><br><span class="line">	</span><br><span class="line">    <span class="built_in">Object</span>.defineProperty(<span class="keyword">this</span>,<span class="string">'skillLevel'</span>,&#123;</span><br><span class="line">        <span class="keyword">get</span>:() =&gt; &#123;</span><br><span class="line">            <span class="keyword">return</span> count;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="keyword">set</span>:value =&gt; &#123;</span><br><span class="line">            <span class="keyword">if</span>(!<span class="built_in">Number</span>.isInteger(value))&#123;</span><br><span class="line">                <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">TypeError</span>(<span class="string">"抛出错误"</span>)</span><br><span class="line">            &#125;</span><br><span class="line">            count = value;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义如何计算属性值 </span></span><br><span class="line"><span class="keyword">const</span> collection = &#123;</span><br><span class="line">    name:<span class="string">'xiaolu'</span>,</span><br><span class="line">    age:<span class="string">'2'</span>,</span><br><span class="line">    <span class="comment">// 读取属性</span></span><br><span class="line">    <span class="keyword">get</span> getName()&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.name + <span class="string">" "</span>+<span class="keyword">this</span>.age;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// 设置属性</span></span><br><span class="line">    <span class="keyword">set</span> setName(value)&#123;</span><br><span class="line">        <span class="keyword">this</span>.name = value;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(collection.getName)</span><br></pre></td></tr></table></figure>



<h3 id="ES6-7-的异步编程"><a href="#ES6-7-的异步编程" class="headerlink" title="ES6/7 的异步编程"></a>ES6/7 的异步编程</h3><p>在之前的 <code>js</code> 基础面试知识一篇中，我们说到了异步编程，留一下一个传送门，直接传送到这里了。上回说到，要想解决函数回调地狱问题，我们要用到 <code>ES6/ES7</code>中的一些内容，在这一节，小鹿会详细的分享~</p>
<h4 id="Generator-生成器"><a href="#Generator-生成器" class="headerlink" title="Generator 生成器"></a>Generator 生成器</h4> <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 Generator 是如何使用的？以及各个阶段的状态是如何变化的？</blockquote>

<p>使用生成器函数可以生成一组值的序列，每个值的生成是基于每次请求的，并不同于标准函数立即生成。</p>
<p>调用生成器不会直接执行，而是通过叫做<strong>迭代器</strong>的对象控制生成器执行。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">WeaponGenerator</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"1"</span>;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"2"</span>;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"3"</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> item <span class="keyword">of</span> WeaponGenerator())&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(item);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//1</span></span><br><span class="line"><span class="comment">//2</span></span><br><span class="line"><span class="comment">//3</span></span><br></pre></td></tr></table></figure>

<p>使用迭代器控制生成器。</p>
<ul>
<li>通过调用生成器返回一个迭代器对象，用来控制生成器的执行。</li>
<li>调用迭代器的 <code>next</code> 方法向生成器请求一个值。</li>
<li>请求的结果返回一个对象，对象中包含一个<code>value</code>值和 <code>done</code>布尔值，告诉我们生成器是否还会生成值。</li>
<li>如果没有可执行的代码，生成器就会返回一个 <code>undefined</code> 值，表示整个生成器已经完成。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">WeaponGenerator</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"1"</span>;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"2"</span>;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"3"</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> weapon = WeaponGenerator();</span><br><span class="line"><span class="built_in">console</span>.log(weapon.next());</span><br><span class="line"><span class="built_in">console</span>.log(weapon.next());</span><br><span class="line"><span class="built_in">console</span>.log(weapon.next());</span><br></pre></td></tr></table></figure>

<p>状态变化如下：</p>
<ul>
<li>每当代码执行到 <code>yield</code> 属性，就会生成一个中间值，返回一个对象。</li>
<li>每当生成一个值后，生成器就会非阻塞的挂起执行，等待下一次值的请求。</li>
<li>再次调用 <code>next</code> 方法，将生成器从挂起状态唤醒，中断执行的生成器从上次离开的位置继续执行。</li>
<li>直到遇到下一个 <code>yield</code> ，生成器挂起。</li>
<li>当执行到没有可执行代码了，就会返回一个结果对象，<code>value</code> 的值为 <code>undefined</code>, <code>done</code> 的值为 <code>true</code>，生成器执行完成。</li>
</ul>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 Generator 内部结构实现？</blockquote>

<p>生成器更像是一个状态运动的状态机。</p>
<ul>
<li>挂起开始状态——创建一个生成器处于未执行状态。</li>
<li>执行状态——生成器的执行状态。</li>
<li>挂起让渡状态——生成器执行遇到第一个 yield 表达式。</li>
<li>完成状态——代码执行到 return 全部代码就会进入全部状态。</li>
</ul>
<p><strong>执行上下文跟踪生成器函数。</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">WeaponGenerator</span>(<span class="params">action</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"1"</span>+action;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"2"</span>;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">"3"</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> Iterator = WeaponGenerator(<span class="string">"xiaolu"</span>);</span><br><span class="line"><span class="keyword">let</span> result1 = Iterator.next()</span><br><span class="line"><span class="keyword">let</span> result2 = Iterator.next()</span><br><span class="line"><span class="keyword">let</span> result3 = Iterator.next()</span><br></pre></td></tr></table></figure>

<ul>
<li>在调用生成器之前的状态——只有全局执行上下文，全局环境中除了生成器变量的引用，其他的变量都为 <code>undefined</code>。</li>
<li>调用生成器并没有执行函数，而是返回一个 <code>Iterator</code>迭代器对象并指向当前生成器的上下文。</li>
<li>一般函数调用完成上下文弹出栈，然后被摧毁。当生成器的函数调用完成之后，当前生成器的上下文出栈，但是在全局的迭代器对象还与保持着与生成器执行上下文引用，且生成器的词法环境还存在。</li>
<li>执行 <code>next</code> 方法，一般的函数会重新创建执行上下文。而生成器会重新激活对应的上下文并推入栈中（这也是为什么标准函数重复调用时，重新从头执行的原因所在。与标准函数相比较，生成器暂时会挂起并将来恢复）。</li>
<li>当遇到 <code>yield</code>关键字的时候，生成器上下文出栈，但是迭代器还是保持引用，处于非阻塞暂时挂起的状态。</li>
<li>如果遇到 <code>next</code> 指向方法继续在原位置继续 执行，直到遇到 <code>return</code> 语句，并返回值结束生成器的执行，生成器进入结束状态。</li>
</ul>
<h4 id="Promise"><a href="#Promise" class="headerlink" title="Promise"></a>Promise</h4> <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 Promise 的原理？你是如何理解 Promise 的？</blockquote>

<p>在深入 <code>Promise</code> 之前，我们先想想 Why（为什么）会有 <code>Promise</code>，<code>Promise</code> 的诞生解决了哪些问题呢？</p>
<p>小鹿总结到的原因有两方面，第一，由于 JS 的运行时单线程的，所以当执行耗时的任务时，就会造成 UI 渲染的阻塞。当前的解决方法是使用回调函数来解决这个问题，当任务执行完毕会，会调用回调方法。</p>
<p>第二就是回调函数存在以下几个缺点：</p>
<ul>
<li>不能捕捉异常（错误处理困难）——回调函数的代码和开始任务代码不在同一事件循环中；</li>
<li>回调地域问题（嵌套回调）；</li>
<li>处理并行任务棘手（请求之间互不依赖）；</li>
</ul>
<p><strong>实现一个简单的 Promise:</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> promise = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve, reject</span>) </span>&#123;</span><br><span class="line">    resolve();</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">promise.then(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"回调成功！"</span>)</span><br><span class="line">&#125;,(err) =&gt;&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"回调失败！"</span>)</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<ul>
<li>通过内置的 <code>Promise</code> 构造函数可以创建一个 <code>Promise</code> 对象，构造函数中传入两个函数参数：<code>resolve</code>，<code>reject</code>。两个参数的作用是，在函数内手动调用 <code>resolve</code> 的时候，就说明回调成功了；调用  <code>reject</code> 说明调用失败。通常在 promise 中进行耗时的异步操作，响应是否成功，我们根据判断就可以调用对应的函数。</li>
<li>调用 <code>Promise</code> 对象内置的方法 <code>then</code>，传入两个函数，一个是成功回调的函数，一个失败回调的函数。当再 <code>promise</code> 内部调用 <code>resolve</code> 函数时，之后就会回调 <code>then</code> 方法里的第一个函数。当调用了 reject 方法时，就会调用<code>then</code> 方法的第二个函数。</li>
<li><code>promise</code> 相当于是一个承诺，当承诺兑现的时候（调用了 <code>resolve</code> 函数），就会调用 then 中的第一个回调函数，在回调函数中做处理。当承诺出现未知的错误或异常的时候（调用了 <code>reject</code> 函数），就会调用 <code>then</code> 方法的第二个回调函数，提示开发者出现错误。</li>
</ul>
<p><strong>Promise 的状态：</strong></p>
<p>其实 <code>Promise</code> 对象用作异步任务的一个占位符，代表暂时还没有获得但在未来获得的值。</p>
<p><code>Promise</code> 共有三种状态，完成状态和拒绝状态状态都是由等待状态转变的。一旦 <code>Promise</code>进入了拒绝或完成状态，它的状态就不能切换了。</p>
<ul>
<li><strong>等待状态（pending）</strong></li>
<li><strong>完成状态（resolve）</strong></li>
<li><strong>拒绝状态（reject）</strong></li>
</ul>
<p><code>Promise</code> 共有两种拒绝状态：显示拒绝（直接调用 <code>reject</code>）和隐式拒绝（抛出异常）。</p>
<p><strong>一个 <code>Promise</code> 实例：</strong></p>
<blockquote>
<p>客户端请求服务器是最常用的异步任务，下面实现一下。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getJson</span>(<span class="params">url</span>)</span>&#123;</span><br><span class="line">    <span class="comment">// 返回一个 promise 对象</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve,reject</span>)=&gt;</span>&#123;</span><br><span class="line">        <span class="keyword">const</span> request = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">        request.open(<span class="string">"GET"</span>,url);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 服务器响应成功</span></span><br><span class="line">        request.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="comment">//try-catch 考虑到 JSON 可能解析会出现错误</span></span><br><span class="line">            <span class="keyword">try</span>&#123;</span><br><span class="line">                <span class="comment">// 响应码正确且 JSON 解析正确</span></span><br><span class="line">                <span class="keyword">if</span>(<span class="keyword">this</span>.status == <span class="number">200</span>)&#123;</span><br><span class="line">                    <span class="comment">// 调用成功承诺</span></span><br><span class="line">                    resolve(<span class="built_in">JSON</span>.parse(<span class="keyword">this</span>.response))</span><br><span class="line">                &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                    <span class="comment">// 调用失败承诺</span></span><br><span class="line">                    reject(<span class="keyword">this</span>.status + <span class="string">" "</span> +<span class="keyword">this</span>.statusText);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;<span class="keyword">catch</span>(e)&#123;</span><br><span class="line">                <span class="comment">// 调用失败承诺</span></span><br><span class="line">                reject(e.message)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 服务器响应失败</span></span><br><span class="line">        request.onerror = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">            <span class="comment">// 调用失败承诺</span></span><br><span class="line">            reject(<span class="keyword">this</span>.status + <span class="string">" "</span> +<span class="keyword">this</span>.statusText);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 发送请求</span></span><br><span class="line">        request.send();</span><br><span class="line"></span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用上述异步请求</span></span><br><span class="line">getJson(<span class="string">"url"</span>).then(<span class="function">(<span class="params">res</span>)=&gt;</span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"解析的JSON数据为:"</span>+res)</span><br><span class="line">&#125;,(res)=&gt;&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">"错误信息："</span>+res)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>



 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：什么是 Promise 链？说说 Promise 如何使用的？</blockquote>

<p><code>promise</code>可以实现链式调用，每次<code>then</code> 之后返回的都是一个<code>promise</code>对象，可以紧接着使用 <code>then</code>继续处理接下来的任务，这样就实现了链式调用。如果在 then 中使用了<code>return</code>，那么 return 的值也会被<code>Promise.resove()</code>包装。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Promise</span>.resolve(<span class="number">1</span>)</span><br><span class="line">  .then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(res) <span class="comment">// =&gt; 1</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">2</span> <span class="comment">// 包装成 Promise.resolve(2)</span></span><br><span class="line">  &#125;)</span><br><span class="line">  .then(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(res) <span class="comment">// =&gt; 2</span></span><br><span class="line">  &#125;)</span><br></pre></td></tr></table></figure>

<p><code>Promise</code> 最常用的使用方式有以下几个方式：</p>
<p><strong>嵌套任务处理：</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 链式回调</span></span><br><span class="line">getJson(<span class="string">"url"</span>)</span><br><span class="line">    .then(<span class="function"><span class="params">n</span> =&gt;</span> &#123;getJson(n[<span class="number">0</span>].url)&#125;)</span><br><span class="line">    .then(<span class="function"><span class="params">m</span> =&gt;</span> &#123;getJson(m[<span class="number">0</span>].url)&#125;)</span><br><span class="line">    .then(<span class="function"><span class="params">w</span> =&gt;</span> &#123;getJson(w[<span class="number">0</span>].url)&#125;)</span><br><span class="line">    .catch((<span class="function"><span class="params">error</span> =&gt;</span> &#123;<span class="built_in">console</span>.log(<span class="string">"异常错误！"</span>)&#125;))</span><br></pre></td></tr></table></figure>

<ul>
<li>因为 <code>then</code>方法会返回一个 <code>promise</code> 对象，所以连续调用 <code>then</code> 方法可以进行链式调用 <code>promise</code>。</li>
<li>多个异步任务中可能出现错误，只需要调用一个 <code>catch</code> 方法并向其传入错误处理的回调函数。</li>
</ul>
<p><strong>并行处理任务：</strong></p>
<p>上述的链式调用主要处理的是多个异步任务之间存在依赖性的，如果同时执行多个异步任务，就是用 <code>promise</code> 中的 <code>all</code> 方法。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment">// 并行处理多个异步任务</span></span><br><span class="line"><span class="built_in">Promise</span>.all([getJson(url),</span><br><span class="line">             getJson(url),</span><br><span class="line">             getJson(url)]).then(<span class="function"><span class="params">resule</span> =&gt;</span> &#123;</span><br><span class="line">                 <span class="comment">// 如果三个请求都响应成功</span></span><br><span class="line">                 <span class="keyword">if</span>(result[<span class="number">0</span>] == <span class="number">1</span> &amp;&amp; result[<span class="number">1</span>] == <span class="number">1</span> &amp;&amp; result[<span class="number">2</span>] == <span class="number">1</span>)&#123;</span><br><span class="line">                     <span class="built_in">console</span>.log(<span class="string">"请求成功！"</span>)</span><br><span class="line">                 &#125;</span><br><span class="line">             &#125;).catch(<span class="function"><span class="params">error</span> =&gt;</span> &#123;<span class="built_in">console</span>.log(<span class="string">"异常错误！"</span>)&#125;)</span><br></pre></td></tr></table></figure>

<ul>
<li>使用 <code>Promise.all()</code>方法进行异步请求，将多个请求任务封装数组进行同步请求。</li>
<li>返回的结果值会打包成一个数组，可以通过数组的下标获取值对返回的结果进行判断。</li>
<li>只有全部请求成功才会进入成功的方法，否则就会调用 <code>catch</code> 抛出异常。</li>
<li>与 <code>Promise.race()</code>方法不同的是，<code>race</code>方法只要其中一个返回成功，就会调用成功的方法。</li>
</ul>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说怎么实现一个 Promise？</blockquote>

<p>我们根据 <code>Promise</code> 的执行顺序，手动实现一个 <code>Promise</code>。</p>
<ul>
<li>先执行 <code>MyPromise</code> 构造函数；</li>
<li>注册 <code>then</code> 函数；</li>
<li>此时的 <code>promise</code> 挂起，<code>UI</code> 非堵塞，执行其他的同步代码；</li>
<li>执行回调函数。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 三种状态</span></span><br><span class="line"><span class="keyword">const</span> PENDING = <span class="string">"pending"</span>;</span><br><span class="line"><span class="keyword">const</span> RESOLVE = <span class="string">"resolve"</span>;</span><br><span class="line"><span class="keyword">const</span> REJECT = <span class="string">"reject"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// promise 函数</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">MyPromise</span>(<span class="params">fn</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">const</span> that = <span class="keyword">this</span>;           <span class="comment">// 回调时用于保存正确的 this 对象</span></span><br><span class="line">    that.state = PENDING;        <span class="comment">// 初始化状态</span></span><br><span class="line">    that.value = <span class="literal">null</span>;           <span class="comment">// value 用于保存回调函数(resolve/reject 传递的参数值)</span></span><br><span class="line">    that.resolvedCallbacks = []; <span class="comment">// 用于保存 then 中的回调</span></span><br><span class="line">    that.rejectedCallbacks = [];</span><br><span class="line"></span><br><span class="line">    <span class="comment">// resolve 和 reject 函数 </span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">resolve</span>(<span class="params">value</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(that.state === PENDING)&#123;</span><br><span class="line">            that.state = <span class="string">'resolve'</span>;</span><br><span class="line">            that.value = value;</span><br><span class="line">            that.resolvedCallbacks.map(<span class="function"><span class="params">cb</span> =&gt;</span> cb(that.value));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">reject</span>(<span class="params">value</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (that.state === PENDING) &#123;</span><br><span class="line">            that.state = <span class="string">'reject'</span></span><br><span class="line">            that.value = value</span><br><span class="line">            that.rejectedCallbacks.map(<span class="function"><span class="params">cb</span> =&gt;</span> cb(that.value))</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 实现如何执行 Promise 中传入的函数</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        fn(resolve, reject)</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">        reject(e)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 实现 then 函数</span></span><br><span class="line">MyPromise.prototype.then = <span class="function"><span class="keyword">function</span>(<span class="params">onResolved, onRejected</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> that = <span class="keyword">this</span>;</span><br><span class="line">    <span class="comment">// 判断两个参数是否为函数类型(如果不是函数，就创建一个函数赋值给对应的参数)</span></span><br><span class="line">    onResolved = <span class="keyword">typeof</span> onResolved === <span class="string">'function'</span> ? onResolved : <span class="function"><span class="params">v</span> =&gt;</span> v;</span><br><span class="line">    onRejected = <span class="keyword">typeof</span> onRejected === <span class="string">'function'</span> ? onRejected : <span class="function"><span class="params">r</span> =&gt;</span> &#123;<span class="keyword">throw</span> r&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 判断当前的状态</span></span><br><span class="line">    <span class="keyword">if</span> (that.state === <span class="string">'pending'</span>) &#123;</span><br><span class="line">        that.resolvedCallbacks.push(onResolved)</span><br><span class="line">        that.rejectedCallbacks.push(onRejected)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (that.state === <span class="string">'resolve'</span>) &#123;</span><br><span class="line">        onResolved(that.value)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (that.state === <span class="string">'reject'</span>) &#123;</span><br><span class="line">        onRejected(that.value)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> MyPromise(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    setTimeout(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">        resolve(<span class="number">1</span>)</span><br><span class="line">    &#125;, <span class="number">0</span>)</span><br><span class="line">&#125;).then(<span class="function"><span class="params">value</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(value)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>



<h4 id="async-及-await"><a href="#async-及-await" class="headerlink" title="async 及 await"></a>async 及 await</h4> <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：async 及 await 和 Generator 以及 Promise 什么区别？它们的优点和缺点分别是什么？await 原理是什么？</blockquote>

<p>其实 <code>ES7</code> 中的 <code>async</code> 及 <code>await</code>就是 <code>Generator</code> 以及 <code>Promise</code> 的语法糖，内部的实现原理还是原来的，只不过是在写法上有所改变，这些实现一些异步任务写起来更像是执行同步任务。</p>
<p><strong>async 及 await 的特点：</strong></p>
<p>一个函数前加上 <code>async</code>关键字，就将该函数返回一个 <code>Promise</code>，<code>async</code>  直接将返回值使用 <code>Promise.resolve()</code> 进行包裹（与 then 处理效果相同）。</p>
<p><code>await</code> 只能配套 <code>async</code> 使用，<code>await</code> 内部实现了 <code>generator</code>，<code>await</code> 就是 <code>generator</code> 加上 <code>Promise</code> 的语法糖，且内部实现了自动执行 <code>generator</code>。</p>
<p><strong>async  和 await 的优缺点？</strong></p>
<ul>
<li><strong>内置执行器。</strong> Generator 函数的执行必须靠执行器，所以才有了 co 函数库，而 async 函数自带执行器。也就是说，async 函数的执行，与普通函数一模一样，只要一行。</li>
<li><strong>更好的语义。</strong> async 和 await，比起星号和 yield，语义更清楚了。async 表示函数里有异步操作，await 表示紧跟在后面的表达式需要等待结果。</li>
<li><strong>更广的适用性。</strong> co 函数库约定，yield 命令后面只能是 Thunk 函数或 Promise 对象，而 async 函数的 await 命令后面，可以跟 Promise 对象和原始类型的值（数值、字符串和布尔值，但这时等同于同步操作）。</li>
</ul>
<p><strong>缺点：</strong></p>
<p>因为 <code>await</code> 将异步代码改造成了同步代码，如果多个异步代码没有依赖性却使用了 <code>await</code> 会导致性能上的降低。</p>
<p><strong>await 原理是什么？</strong></p>
<p><code>async</code> 函数的实现，就是将 <code>Generator</code>函数和自动执行器，包装在一个函数里。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">spawn</span>(<span class="params">genF</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve, reject</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> gen = genF();</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">step</span>(<span class="params">nextF</span>) </span>&#123;</span><br><span class="line">      <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">var</span> next = nextF();</span><br><span class="line">      &#125; <span class="keyword">catch</span>(e) &#123;</span><br><span class="line">        <span class="keyword">return</span> reject(e); </span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span>(next.done) &#123;</span><br><span class="line">        <span class="keyword">return</span> resolve(next.value);</span><br><span class="line">      &#125; </span><br><span class="line">      <span class="built_in">Promise</span>.resolve(next.value).then(<span class="function"><span class="keyword">function</span>(<span class="params">v</span>) </span>&#123;</span><br><span class="line">        step(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; <span class="keyword">return</span> gen.next(v); &#125;);      </span><br><span class="line">      &#125;, <span class="function"><span class="keyword">function</span>(<span class="params">e</span>) </span>&#123;</span><br><span class="line">        step(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; <span class="keyword">return</span> gen.throw(e); &#125;);</span><br><span class="line">      &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    step(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; <span class="keyword">return</span> gen.next(<span class="literal">undefined</span>); &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>





<h3 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h3> <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：为什么要使用模块化？都有哪几种方式可以实现模块化，各有什么特点？</blockquote>

<p>模块化解决了命名冲突问题，可以提高代码的复用率，提高代码的可维护性。</p>
<p>模块化的好处:</p>
<ul>
<li><strong>避免命名冲突(减少命名空间污染)</strong></li>
<li><strong>更好的分离, 按需加载</strong></li>
<li><strong>更高复用性</strong></li>
<li><strong>高可维护性</strong></li>
</ul>
<h4 id="方式一：函数"><a href="#方式一：函数" class="headerlink" title="方式一：函数"></a>方式一：函数</h4><p>最起初，实现模块化的方式使用函数进行封装。将不同功能的代码实现封装到不同的函数中。通常一个文件就是一个模块，有自己的作用域，只向外暴露特定的变量和函数。 </p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="comment">// 功能二</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">b</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="comment">// 功能一</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>缺陷：</strong>容易发生命名冲突或者数据的不安全性。</p>
<h4 id="方式二：立即执行函数"><a href="#方式二：立即执行函数" class="headerlink" title="方式二：立即执行函数"></a>方式二：立即执行函数</h4><p>立即执行函数中的匿名函数中有独立的 词法作用域，避免了外界访问此作用域的变量。<strong>通过函数作用域解决了命名冲突、污染全局作用域的问题</strong> 。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// module.js文件</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params">window</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">let</span> name = <span class="string">'xiaolu'</span></span><br><span class="line">  <span class="comment">// 暴露的接口来访问数据</span></span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">a</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`name:<span class="subst">$&#123;name&#125;</span>`</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//暴露接口</span></span><br><span class="line">  <span class="built_in">window</span>.myModule = &#123; a &#125; </span><br><span class="line">&#125;)(<span class="built_in">window</span>)</span><br></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span> <span class="attr">src</span>=<span class="string">"module.js"</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>&gt;</span></span><br><span class="line"><span class="actionscript">    myModule.name = <span class="string">'xixi'</span> <span class="comment">// 无法访问</span></span></span><br><span class="line"><span class="actionscript">    myModule.foo()  <span class="comment">// name:xiaolu</span></span></span><br><span class="line"><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h4 id="方式三：CommonJS"><a href="#方式三：CommonJS" class="headerlink" title="方式三：CommonJS"></a>方式三：CommonJS</h4><ul>
<li><code>CommonJS</code> 的规范主要用在 <code>Node.js</code> 中，为模块提供了四个接口：<code>module、exports、require、global</code>。</li>
<li><code>CommonJS</code> 用同步的方式加载模块（服务器端），在浏览器端使用的是异步加载模块。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// lib.js</span></span><br><span class="line"><span class="keyword">var</span> counter = <span class="number">3</span>;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">incCounter</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    counter++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 对外暴露接口</span></span><br><span class="line"><span class="built_in">module</span>.exports = &#123;</span><br><span class="line">    counter: counter,</span><br><span class="line">    incCounter: incCounter,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 加载外部模块</span></span><br><span class="line"><span class="keyword">var</span> mod = <span class="built_in">require</span>(<span class="string">'./lib'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(mod.counter);  <span class="comment">// 3</span></span><br><span class="line">mod.incCounter();</span><br><span class="line"><span class="comment">// 原始类型的值被缓存，所以就没有被改变（commonJS 不会随着执行而去模块随时调用）</span></span><br><span class="line"><span class="built_in">console</span>.log(mod.counter); <span class="comment">// 3</span></span><br></pre></td></tr></table></figure>

<p><strong>加载机制：</strong></p>
<p><code>CommonJS</code> 模块的加载机制是，输入的是被输出的值的拷贝。也就是说，一旦输出一个值，模块内部的变化就影响不到这个值。</p>
<p><strong>特点：</strong></p>
<ul>
<li>所有代码都运行在模块作用域，不会污染全局作用域。</li>
<li>模块可以多次加载，但是只会在第一次加载时运行一次，然后运行结果就被缓存了，以后再加载，就直接读取缓存结果。要想让模块再次运行，必须清除缓存。</li>
<li>模块加载的顺序，按照其在代码中出现的顺序。</li>
</ul>
<h4 id="方式四：AMD-和-CMD"><a href="#方式四：AMD-和-CMD" class="headerlink" title="方式四：AMD 和 CMD"></a>方式四：AMD 和 CMD</h4><p>有关 AMD 和 CMD  就不多说了，详细请看这篇文章。</p>
<p><a href="https://www.zhihu.com/question/20351507/answer/14859415" target="_blank" rel="noopener">AMD 和 CMD 的区别有哪些？</a></p>
 <blockquote style="position: relative;border-left-color: #f75151;margin-left: 8px;padding:15px 23px;background:#f8f8f8;color:#666;">
    <p>面试官：说说 ES6 中的模块化？CommonJS 和 ES6 模块化的区别？</blockquote>

<h4 id="方式五：ES6-Moudle"><a href="#方式五：ES6-Moudle" class="headerlink" title="方式五：ES6 Moudle"></a>方式五：ES6 Moudle</h4><p>ES6 实现的模块非常简单，用于浏览器和服务器端。<code>mport</code>命令会被 JavaScript 引擎静态分析，在编译时就引入模块代码 .主要有两个命令组成：<code>export</code>和<code>import</code>:</p>
<ul>
<li><code>export</code>命令用于规定模块的<strong>对外接口</strong>。</li>
<li><code>import</code>命令引入其他模块的功能。 </li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 指定指定的值暴露对外的接口</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">let</span> counter = <span class="number">3</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">incCounter</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  counter++;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 加载模块中的某个值</span></span><br><span class="line"><span class="keyword">import</span> &#123; counter, incCounter &#125; <span class="keyword">from</span> <span class="string">'./lib'</span>;</span><br><span class="line"><span class="built_in">console</span>.log(counter); <span class="comment">// 3</span></span><br><span class="line">incCounter();</span><br><span class="line"><span class="comment">// ES6 模块不同的是，静态加载完毕之后，每执行到模块中的方法，就去模块内调用（外部的变量总是与模块进行绑定的），而且值不会被缓存。</span></span><br><span class="line"><span class="built_in">console</span>.log(counter); <span class="comment">// 4</span></span><br></pre></td></tr></table></figure>



<p><strong>ES6 模块与 CommonJS 模块的区别：</strong></p>
<ul>
<li><strong>CommonJS 模块输出的是一个值的拷贝，ES6 模块输出的是值的引用。</strong><ul>
<li>所谓值的拷贝，原始类型的值被缓存，不随模块内部的改变而改变。</li>
<li>ES6 模块是<strong>动态引用</strong>，<strong>不缓存值</strong>，模块内外是<strong>绑定</strong>的，而且是<strong>只读引用</strong>，不能修改值。ES6 的 js 引擎对脚本静态分析的时候，遇到加载命令模块 <code>import</code> ，就会生成一个只读引用，当真正用到模块里边的值的时候，就会去模块内部去取。</li>
</ul>
</li>
<li><strong>CommonJS 模块是运行时加载，ES6 模块是编译时加载输出接口。</strong><ul>
<li><strong>运行时加载</strong>：<code>CommonJS</code> 模块就是对象；是先加载整个模块，生成一个对象，然后再从这个对象上面读取方法，这种加载称为“运行时加载”。 </li>
<li><strong>编译时加载：</strong>ES6 模块不是对象，而是通过 <code>export</code> 命令「显式指定输出的代码」。<code>import</code> 时采用静态命令的形式，即在<code>import</code>指定「加载某个输出值」，而「不是加载整个模块」，这种加载称为“编译时加载”。 </li>
</ul>
</li>
</ul>
<h4 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h4><ul>
<li><code>CommonJS</code> 规范主要用于服务端编程，加载模块是同步的，这并不适合在浏览器环境，因为同步意味着阻塞加载，浏览器资源是异步加载的，因此有了<code>AMD CMD</code>解决方案。</li>
<li><code>AMD</code> 规范在浏览器环境中异步加载模块，而且可以并行加载多个模块。不过，<code>AMD</code> 规范开发成本高，代码的阅读和书写比较困难，模块定义方式的语义不顺畅。</li>
<li><code>CMD</code> 规范与 <code>AMD</code>  规范很相似，都用于浏览器编程，依赖就近，延迟执行，可以很容易在 <code>Node.js</code> 中运行。不过，依赖 <code>SPM</code> 打包，模块的加载逻辑偏重。</li>
<li><strong>ES6 在语言标准的层面上，实现了模块功能，而且实现得相当简单，完全可以取代 CommonJS 和 AMD 规范，成为浏览器和服务器通用的模块解决方案</strong>。</li>
</ul>

      
    </div>
    <div id="comments">
      <blockquote class="mt-2x">
  <ul class="post-copyright list-unstyled">
    
    <li class="post-copyright-link hidden-xs">
      <strong>本文链接：</strong>
      <a style="word-wrap:break-word;" href="http://yoursite.com/2020/03/19/01/Web-interview/README/" title="大前端吊打面试官系列" target="_blank" rel="external">http://yoursite.com/2020/03/19/01/Web-interview/README/</a>
    </li>
    
    <li class="post-copyright-license">
      <strong>版权声明： </strong> 本博客所有文章除特别声明外，均采用 <a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN协议</a> 许可协议。转载请注明出处！
    </li>
  </ul>
</blockquote>


<div class="panel panel-default panel-badger">
  <div class="panel-body">
    <figure class="media">
      <div class="media-left">
        <a href="https://github.com/chen08" target="_blank" class="img-burn thumb-sm visible-lg">
          <img src="/images/avatar.jpg" class="img-rounded w-full" alt="">
        </a>
      </div>
      <div class="media-body">
        <h3 class="media-heading"><a href="https://github.com/chen08" target="_blank"><span class="text-dark">溟海</span><small class="ml-1x">Web Developer &amp; Designer</small></a></h3>
        <div>天行健，君子以自强不息，地势坤，君子以厚德载物。 杀不死我的,终将使我强大 没有吃不了的苦,只有享不了的福</div>
      </div>
    </figure>
  </div>
</div>


    </div>
  </article>
  
    
  <section id="comments">
  	
      <div id="vcomments"></div>
    
  </section>


  
</div>

  <nav class="bar bar-footer clearfix" data-stick-bottom>
  <div class="bar-inner">
  
  <ul class="pager pull-left">
    
    <li class="prev">
      <a href="/2020/03/23/06/%E5%88%98%E5%AA%9B%E5%AA%9B%C2%B7%E5%8C%97%E5%A4%A7%E5%AD%A6%E9%9C%B8%E6%95%99%E4%BD%A0%E9%AB%98%E6%95%88%E5%AD%A6%E4%B9%A0%E7%9A%84%E7%A7%98%E5%AF%86%EF%BC%88%E8%AF%BE%E7%A8%8B%E8%B5%84%E6%96%99%EF%BC%89/" title="刘媛媛·北大学霸教你高效学习的秘密（课程资料）"><i class="icon icon-angle-left" aria-hidden="true"></i><span>&nbsp;&nbsp;Newer</span></a>
    </li>
    
    
    <li class="next">
      <a href="/2020/03/17/05/English/%E8%B0%A2%E5%AD%9F%E5%AA%9B%E7%9A%84%E6%96%87%E6%B3%95/" title="谢孟媛的文法"><span>Older&nbsp;&nbsp;</span><i class="icon icon-angle-right" aria-hidden="true"></i></a>
    </li>
    
    
    <li class="toggle-toc">
      <a class="toggle-btn collapsed" data-toggle="collapse" href="#collapseToc" aria-expanded="false" title="Catalogue" role="button">
        <span>[&nbsp;</span><span>Catalogue</span>
        <i class="text-collapsed icon icon-anchor"></i>
        <i class="text-in icon icon-close"></i>
        <span>]</span>
      </a>
    </li>
    
  </ul>
  
  
  <!-- Button trigger modal -->
  <button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal" data-target="#donateModal"><span>$</span></button>
  <!-- <div class="wave-icon wave-icon-danger btn-donate" data-toggle="modal" data-target="#donateModal">
    <div class="wave-circle"><span class="icon"><i class="icon icon-bill"></i></span></div>
  </div> -->
  
  
  <div class="bar-right">
    
    <div class="share-component" data-sites="weibo,qq,wechat,facebook,twitter" data-mobile-sites="weibo,qq,qzone"></div>
    
  </div>
  </div>
</nav>
  
<!-- Modal -->
<div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content donate">
      <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      <div class="modal-body">
        <div class="donate-box">
          <div class="donate-head">
            <p>Maybe you could buy me a cup of coffee.</p>
          </div>
          <div class="tab-content">
            <div role="tabpanel" class="tab-pane fade active in" id="alipay">
              <div class="donate-payimg">
                <img src="/images/donate/alipayimg.png" alt="Scan Qrcode" title="Scan" />
              </div>
              <p class="text-muted mv">Scan this qrcode</p>
              <p class="text-grey">Open alipay app scan this qrcode, buy me a coffee!</p>
            </div>
            <div role="tabpanel" class="tab-pane fade" id="wechatpay">
              <div class="donate-payimg">
                <img src="/images/donate/wechatpayimg.png" alt="Scan Qrcode" title="Scan" />
              </div>
              <p class="text-muted mv">Scan this qrcode</p>
              <p class="text-grey">Open wechat app scan this qrcode, buy me a coffee!</p>
            </div>
          </div>
          <div class="donate-footer">
            <ul class="nav nav-tabs nav-justified" role="tablist">
              <li role="presentation" class="active">
                <a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay" aria-expanded="true"><i class="icon icon-alipay"></i> alipay</a>
              </li>
              <li role="presentation" class="">
                <a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab" aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i> wechat payment</a>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>



</main>

  <footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
	
	
    <ul class="social-links">
    	
        <li><a href="https://github.com/cofess" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="http://weibo.com/cofess" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="https://twitter.com/iwebued" target="_blank" title="Twitter" data-toggle=tooltip data-placement=top><i class="icon icon-twitter"></i></a></li>
        
        <li><a href="https://www.behance.net/cofess" target="_blank" title="Behance" data-toggle=tooltip data-placement=top><i class="icon icon-behance"></i></a></li>
        
        <li><a href="/atom.xml" target="_blank" title="Rss" data-toggle=tooltip data-placement=top><i class="icon icon-rss"></i></a></li>
        
    </ul>

    <div class="copyright">
    	
        <div class="publishby">
        	Theme by <a href="https://github.com/cofess" target="_blank"> cofess </a>base on <a href="https://github.com/cofess/hexo-theme-pure" target="_blank">pure</a>.
        </div>
    </div>
</footer>
  <script src="//cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>

<script src="/js/plugin.min.js"></script>


<script src="/js/application.js"></script>


    <script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: 'Posts',
            PAGES: 'Pages',
            CATEGORIES: 'Categories',
            TAGS: 'Tags',
            UNTITLED: '(Untitled)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>

<script src="/js/insight.js"></script>






   


<!-- custom analytics part create by xiamo -->
<script  src="https://cdn1.lncld.net/static/js/av-min-1.2.1.js"></script>
<!-- <script defer src="/js/av-min-1.2.1.js"></script> -->
<script >
AV.init({
  appId: 'ngFQzHw7z0HgQfrtn4En4WTN-gzGzoHsz',
  appKey: 'W9hgBBfVDwRGJKoGp5a6HKpx'
});

function showTime(Counter) {
	var query = new AV.Query(Counter);
		var visitors= $('.leancloud_visitors');
		query.greaterThanOrEqualTo("time", 0);		
		query.find({
			success: function(results) {
				if (results.length == 0) {				
					return;
				}
				var data = results;
				visitors.each(function(){
					var url = $(this).attr('id').trim();					
					for (var i = 0; i < data.length; i++) {
						var object = data[i];
						var content = object.get('time');
						var _url = object.get('url')
						if(url == _url){
							$(this).text(content);
						}
					}
				})
				
			},
			error: function(object, error) {
				console.log("Error: " + error.code + " " + error.message);
			}
		});
}

function addCount(Counter) {
	var Counter = AV.Object.extend("Counter");
	url = $(".leancloud_visitors").attr('id').trim();
	title = $(".leancloud_visitors").attr('data-flag-title').trim();
	var query = new AV.Query(Counter);
	query.equalTo("url", url);
	query.find({
		success: function(results) {
			if (results.length > 0) {
				var counter = results[0];
				counter.fetchWhenSave(true);
				counter.increment("time");
				counter.save(null, {
					success: function(counter) {
						var content = counter.get('time');
						$(document.getElementById(url)).text(content);
					},
					error: function(counter, error) {
						console.log('Failed to save Visitor num, with error message: ' + error.message);
					}
				});
			} else {
				var newcounter = new Counter();
				newcounter.set("title", title);
				newcounter.set("url", url);
				newcounter.set("time", 1);
				newcounter.save(null, {
					success: function(newcounter) {
					    console.log("newcounter.get('time')="+newcounter.get('time'));
						var content = newcounter.get('time');
						$(document.getElementById(url)).text(content);
					},
					error: function(newcounter, error) {
						console.log('Failed to create');
					}
				});
			}
		},
		error: function(error) {
			console.log('Error:' + error.code + " " + error.message);
		}
	});
}
$(function() {
	var Counter = AV.Object.extend("Counter");
	if ($('.leancloud_visitors').length == 1) {
		addCount(Counter);
	} else {
		showTime(Counter);
	}
}); 
</script>



   
    
  <!-- <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script> -->
  <script src="//cdn.jsdelivr.net/npm/valine"></script>
  <script type="text/javascript">
  var GUEST = ['nick', 'mail', 'link'];
  var meta = 'nick,mail,link';
  meta = meta.split(',').filter(function(item) {
    return GUEST.indexOf(item) > -1;
  });
  new Valine({
    el: '#vcomments',
    verify: false,
    notify: false,
    appId: '',
    appKey: '',
    placeholder: 'Just go go',
    avatar: 'mm',
    meta: meta,
    pageSize: '10' || 10,
    visitor: false
  });
  </script>

     







</body>
</html>